I am trying to bind two list values into a single list based on the values of the column.
below is the list am getting it.
TestCaseName Screen IEStatus IEPath FFStatus FFPath GCStatus GCPath
--------------------------------------------------------------------------------------------
TC001 Yes Pass C:\\a.jpg null null null null
TC002 Yes Pass C:\\b.jpg null null null null
TC001 Yes null null Pass C:\\c.jpg null null
TC002 Yes null null Pass C:\\d.jpg null null
But I want to combine the values and display as below
TestCaseName Screen IEStatus IEPath FFStatus FFPath GCStatus GCPath
--------------------------------------------------------------------------------------------
TC001 Yes Pass C:\\a.jpg Pass C:\\c.jpg null null
TC002 Yes Pass C:\\b.jpg Pass C:\\d.jpg null null
Below is my code
List<ResultProperties> lstCommon = new List<ResultProperties>();
List<ResultProperties> lstNew= new List<ResultProperties>();
var checked_boxes = this.Controls.OfType<CheckBox>().Where(c => c.Checked);
foreach (CheckBox cbx in checked_boxes)
{
Program obj = new Program();
lstNew = obj.PerformTest(cbx.Text, textBox1.Text);
foreach (ResultProperties item in lstNew)
{
lstCommon.Add(item);
}
}
Any suggestions will be greatly helpful..
Rather than doing it in a single Linq expression, I would probably do something list this, so as to avoid multiple iterations over the source data:
List<ResultProperties> a = LoadSourceList() ;
IEnumerable<IGrouping<string,ResultProperties> groups =
a
.GroupBy( x => x.TestCaseName , StringComparer.OrdinalIgnoreCase )
;
List<ResultProperties> coalesced = new List<ResultProperties>() ;
foreach( IGrouping<string,ResultProperties> group in groups )
{
ResultProperties item = null ;
foreach( ResultProperty rp in group )
{
item = item ?? rp ;
item.Screen = item.Screen ?? rp.Screen ;
item.IEStatus = item.IEStatus ?? rp.IEStatus ;
item.IEPath = item.IEPath ?? rp.IEPath ;
item.FFStatus = item.FFStatus ?? rp.FFStatus ;
item.FFPath = item.FFPath ?? rp.FFPath ;
item.GCStatus = item.GCStatus ?? rp.GCStatus ;
item.GCPath = item.GCPath ?? rp.GCPath ;
}
coalesced.Add(item) ;
}
At the end of the day, the source list is unchanged and coalesced should contain a single ResultProperties for each distinct test case name, with all the value coalesce on a first-wins strategy (the first non-null value for a property defines the property for the group).
You should be able to do this with GroupBy, like this:
var res = testData
.GroupBy(test => test.TestCaseName)
.Select(g => new ResultProperties {
TestCaseName = g.Key
, Screen = g.Select(test => test.Screen).FirstOrDefault()
, IEStatus = g.Select(test => test.IEStatus).FirstOrDefault()
, IEPath = g.Select(test => test.IEPath).FirstOrDefault()
, FFStatus = g.Select(test => test.FFStatus).FirstOrDefault()
, FFPath = g.Select(test => test.FFPath).FirstOrDefault()
, GCStatus = g.Select(test => test.GCStatus).FirstOrDefault()
, GCPath = g.Select(test => test.GCPath).FirstOrDefault()
}).ToList();
The idea is to form groups based on the name of the test, and then grab the first non-null entry for each attribute in the group.
Related
I would like to get a specific select with the best performance possible
I currently have a code like this:
var getData = from x in dbContex.MyTable
where x.Car == "audi"
select x;
MyTable has three columns:
Car
ProductionYear
Color
I would like to download a specific vehicle brand with the year of manufacture that has a specific color.
I am currently doing it with reference to the code above:
foreach (var item in getData)
{
if (item.color == "blue") item.ProductionYear = "1999";
if (item.color == "red") item.ProductionYear = "2003";
// etc (...)
}
I would like to assign a specific year for a given car and color if I find it.
A very prosaic example above.
Problem - I currently have 100 colors and only want to check 10 colors.
How can I do it faster so as not to search the entire list and not to use IF statements?
Create an array of the colors, then use Contains method in the predicate expression:
var colors = new [] { "red", "blue" };
var results = dbContext.MyTable
.Where( x => "audi" == x.Car
&& colors.Contains( x.color ) );
Then use a switch statement to assign your years:
foreach(var car in results)
{
car.ProductionYear = car.color switch
{
"blue" => 1999,
"red" => 2003,
_ => // unexpected result, throw exception
}
}
You could also define the years with the colors then work the year assignment into the LINQ query:
var colorYears = new []
{
new {
color = "red",
ProductionYear = 2003,
},
...
};
var colors = colorYears.Select( x => x.color ).ToArray();
var results = (...query from above...)
// enumerate
.ToArray()
// join datasource results with your colorYears array
// on the `color` property
.Join( colorYears,
c => c.color,
cy => cy.color,
( c, cy ) =>
{
// assign the configured production year for the color
c.ProductionYear = cy.ProductionYear;
// return the entity
return c;
} );
There is no scenario, where you don`t use if or switch clause. You want to change data, which is not LINQ case. Only thing I would do - go to switch, rather than If clause.
I don't want to create a new thread so I will write here - a question about LINQ of course and data comparison in the array
I have this code:
var dataTest = (dbContex.MyTable.Where(x => x.col1 == str1
&& x.col2 == str2 && x.col3 == str3).Select(x => x.ID ).FirstOrDefault());
I want to check if there is such a row for these three fields and get its ID - everything is fine when I have values, but when any field is NULL - it cannot compare it and returns information that there is no such record.
the goal is to check if there is a duplicate with these values ββin MyTable based on these three fields - except that each of these fields can be NULL
how best to compare NULL?
I need to write something that would give the same result as:
var result = collection.Where( o => o.Name.IndexOf( "some_string2" ) != -1 || o.Name.IndexOf( "some_string_2" ) != -1 || o.Name.IndexOf( "some_string3" ) != -1 )
Where the amount and values of the strings to check for (some_string_1, 2 and 3) are unknown (coming from DB), so something more generic...
I tried the following, but failed...
var stringsToCheck = someCommaSeparatedStrings.ToLower().Split( ',' ).ToList();
var result = collection.Where( o => stringsToCheck.Contains( o.ToLower() ) );
In other words, I need to retrieve all the objects from a collection which names contain some specific strings.
var result = collection.Where(item => stringsToCheck.Any(stringToCheck =>
item.Name.Contains(stringToCheck)));
Read in English this is: give me all of the items in the collection where, of all of the strings to check one of them is a substring of the string in the collection.
If you want to test whether o.Name contains a stringToCheck then:
var result = collection.Where( o => stringsToCheck.Any(a => o.Name.Contains(a)));
If you only need to test for equality, then:
var result = collection.Where( o => stringsToCheck.Contains(o.Name));
Note: if you need to apply case normalisation then ToLower() should be applied accordingly.
You are checking the collections element o.ToLower() i assume you must check for its name o.Name.ToLower().
If you want to check whether o.Name contains some string from the stringsToCheck, I would suggest to use LinqKit and build the query with PredicateBuilder.
var predicate = PredicateBuilder.False<TypeOfYourObject>();
var stringsToCheck = someCommaSeparatedStrings.ToLower().Split( ',' ).ToList();
foreach(var str in stringsToCheck)
{
var tmp = str;
predicate = predicate.Or(o=> o.Name.IndexOf(tmp) != -1);
}
resultQuery = collection.Where(predicate);
I have a following GroupBy query:
var groups = ordered.GroupBy(k => new
{
a = k[SelectedFirstCategory],
b = k[SelectedSecondCategory],
c = k[SelectedThirdCategory]
});
The problem is that Categories can be null.
How can I modify my GroupBy to accomodate for this. I know I could go with multiple "if" but that is not elegant for me.
To make this clearer an example would be that if SelectedSecondCategory is null but other are filled than resulting grouping should be according to "a" and "c" property.
I thought about null coalescent like this:
a = SelectedFirstCategory != null ? k[SelectedFirstCategory] : DON'T KNOW WHAT TU PUT HERE.
Alternative value should be something that would be irrelevant to groupBy.
Thanks in advance.
I appears to be quite easy:
var groups = ordered.GroupBy(k => new {
a = !String.IsNullOrEmpty(SelectedFirstCategory) ? k[SelectedFirstCategory] : null,
b = !String.IsNullOrEmpty(SelectedSecondCategory) ? k[SelectedSecondCategory] : null,
c = !String.IsNullOrEmpty(SelectedThirdCategory) ? k[SelectedThirdCategory] : null
});
It appears that if some parameter of grouping is null it is not taken into consideration when creating a group so that is what I wanted.
Use a helper method, Just be aware that you grouping may not make any sense. Suppose you had you columns being "Fruit", "Color", "Shape". Grouping ["Apple", "Red", "Round"] with ["Banana", "Oval"] doesn't give good results.
static void Main(string[] args)
{
List<List<object>> ordered = new List<List<object>>();
int SelectedFirstCategory = 1;
int SelectedSecondCategory = 2;
int SelectedThirdCategory = 3;
var groups = ordered.GroupBy(k => MyGroup(
k[SelectedFirstCategory],
k[SelectedSecondCategory],
k[SelectedThirdCategory])
);
}
static List<object> MyGroup(object a, object b, object c)
{
List<object> results = new List<object>();
if (a != null) results.Add(a);
if (b != null) results.Add(b);
if (c != null) results.Add(c);
return results;
}β
How do I express this in NHibernate?
DECLARE #EntityId INT = 800;
SELECT *
FROM UserAlert
WHERE UserAlertId =
(
SELECT MAX(UserAlertId)
FROM UserAlert
WHERE EntityId = #EntityId
)
This is what I'm trying to do.
var senderUA = session.CreateCriteria<UserAlert>()
.Add(Restrictions.Eq("EntityId", id))
.SetProjection( Projections.Max("Id") )
. UniqueResult();
And I keep getting an error that can convert object to UserAlert type, i.e. it's not even compiling.
Thanks for helping
Ordering by UserAlertId descending and selecting top 1 would be simpler.
var senderUA = session.CreateCriteria<UserAlert>()
.Add(Restrictions.Eq("EntityId", id))
.AddOrder(Order.Desc("UserAlertId"))
.SetMaxResults(1)
.UniqueResult();
Additionally you can
var senderUA = session
.Query<UserAlert>()
.Where(x=>x.EntityId==id &&
x.UserAlertId==session.Query<UserAlert>()
.Where(x=>x.EntiryId==id).Max(x=>x.UserAlertId)
).FirstOrDefault();
Here's a solution using QueryOver.
var maxUserAlertId = QueryOver.Of<UserAlert>
.Where(ua => ua.EntityId == id)
.Select(
Projections.Max(
Projections.Property<UserAlert>
(u => u.UserAlertId)
)
);
var maxUserQuery = session
.QueryOver<UserAlert>()
.WithSubquery
.WhereProperty(u => u.EntityId)
.Eq(maxUserAlertId);
// Dealing with the situation that the maximum value is shared
// by more than one row. If you're certain that it can only
// be one, call SingleOrDefault instead of List
IList<UserAlert> results = maxUserQuery.List();
I need to write something that would give the same result as:
var result = collection.Where( o => o.Name.IndexOf( "some_string2" ) != -1 || o.Name.IndexOf( "some_string_2" ) != -1 || o.Name.IndexOf( "some_string3" ) != -1 )
Where the amount and values of the strings to check for (some_string_1, 2 and 3) are unknown (coming from DB), so something more generic...
I tried the following, but failed...
var stringsToCheck = someCommaSeparatedStrings.ToLower().Split( ',' ).ToList();
var result = collection.Where( o => stringsToCheck.Contains( o.ToLower() ) );
In other words, I need to retrieve all the objects from a collection which names contain some specific strings.
var result = collection.Where(item => stringsToCheck.Any(stringToCheck =>
item.Name.Contains(stringToCheck)));
Read in English this is: give me all of the items in the collection where, of all of the strings to check one of them is a substring of the string in the collection.
If you want to test whether o.Name contains a stringToCheck then:
var result = collection.Where( o => stringsToCheck.Any(a => o.Name.Contains(a)));
If you only need to test for equality, then:
var result = collection.Where( o => stringsToCheck.Contains(o.Name));
Note: if you need to apply case normalisation then ToLower() should be applied accordingly.
You are checking the collections element o.ToLower() i assume you must check for its name o.Name.ToLower().
If you want to check whether o.Name contains some string from the stringsToCheck, I would suggest to use LinqKit and build the query with PredicateBuilder.
var predicate = PredicateBuilder.False<TypeOfYourObject>();
var stringsToCheck = someCommaSeparatedStrings.ToLower().Split( ',' ).ToList();
foreach(var str in stringsToCheck)
{
var tmp = str;
predicate = predicate.Or(o=> o.Name.IndexOf(tmp) != -1);
}
resultQuery = collection.Where(predicate);