Getting one list from another list using LINQ - c#

I've seen the technique of taken a list of ObjectA and converting into a list of ObjectB where the two classes share some similar properties but is there an easier way to do that when you're just going from a list of ObjectA to another list of ObjectA?
Basically I want to do ...
var excv = from AuditedUser in data
where AuditedUser.IsMarkedForRemoval == false
select AuditedUser;
... but instead of a var I want the results to form a new List < AuditedUser > .
Is there something super easy I'm just missing?

var excv = (from AuditedUser in data
where AuditedUser.IsMarkedForRemoval == false
select AuditedUser).ToList();
I wrapped your LINQ statement with parens and added the ToList call at the end. Is this what you're looking for?
You could also do the following which is shorter to type and read I think:
List<AuditUser> excv = data.Where(a=>!a.IsMarkedForRemoval).ToList();

Related

How to filter In memory Data object with LINQ and "In" statement

I'm trying to fill my DataGrid
dgGoals.ItemsSource = GetGoals(new int[] { 1, 2, 3 });
This is the In Memory object that has data loaded from a different process
static ObservableCollection<Goal> goals = new ObservableCollection<Goal>();
I tried using this example Linq version of SQL "IN" statement but both the lambda and LINQ statements are returning null when it should be 100 records.
public static ObservableCollection<Goal> GetGoals(int[] selectedGoalKey)
{
//goals has 170 records at this point
//selectedGoalKey has 3 items (1,2,3)
//goals has 100 records with Goal_Key of 1,2 or 3
//Returns null
return goals.Where(f => selectedGoalKey.Contains(f.Goal_Key)) as ObservableCollection<Goal>;
//Returns null
return (from g in _Goals
where selectedGoalKey.Contains(g.Goal_Key)
select g) as ObservableCollection<Goal>;
}
EDIT Fixed and now works
public static IEnumerable<Goal> GetGoals(int[] selectedGoalKey)
{
//goals has 170 records at this point
//selectedGoalKey has 3 items (1,2,3)
//goals has 100 records with Goal_Key of 1,2 or 3
//Now returns 100 records
return goals.Where(f => selectedGoalKey.Contains(f.Goal_Key));
//Now returns 100 records
return (from g in _Goals
where selectedGoalKey.Contains(g.Goal_Key)
select g);
}
The problem is that the result is not an ObservableCollection<Goal> but an IEnumerable<Goal>. That is why you are receiving null.
You can do:
return new ObservableCollecion<Goal>
(goals.Where(f => selectedGoalKey.Contains(f.Goal_Key)));
Using the "x" as "some type" casts the object to that type, and in the case it isn't able to returns null. What you want to do is to create a new ObservableCollecion and pass it the result of the linq query.
Out of MSDN:
The as operator is like a cast operation. However, if the conversion isn't possible, as returns null instead of raising an exception. Consider the following example:
Jmyster is not a good idea to work with ObservableCollection from the begining
Even with it inherits from Collection, it has much more boiler plates than you need while working on simple filters.(stuff like Notify events and more )
I´d strongly recommend you to make all your filltering using simple List, and only in the end of your algorithm put them all in a ObservableCollection class.
This simple behavior will prevent you from dealling with out-of-contexto problems.
Hope this help.

C# use LINQ to query custom list and return new subset list

I have a list of a custom type called Holdings. I am trying to query the list based on one property of the Holdings object to return a new list of Holdings. The LINQ query below does work correctly but I would like to replace var unitHld with List unitHld but can't get the code to work.
var unitHld = from hld in _holdingList
where hld.FundCode == lookThroList[i].FundCode
select new Holding() { Currency = hld.Currency,
FundCode = lookThroList[i].FundCode,
IdSedol = hld.IdSedol,
Nominal = hld.Nominal * unitWgt,
Price = hld.Price };
This new list is then slightly altered before being added back to the original list (I know the logic sounds strange but please accept this is how it has to be done). However because unitHld is var the line below does not work.
_holdingList.Add(unitHld);
The following call only adds a single item (where the item must be the same type as the list's elements):
_holdingList.Add(unitHld);
But you want to add a range of items, so do it like this:
_holdingList.AddRange(unitHld);
where unitHld is IEnumerable<T> and T is the type of the list's elements.
(This answer assumes that holdingList is of type List<T>, and that T is in fact Holding for your example.)
See List.AddRange() for details.
C# is statically typed.
var is not a type, all it does is a shortcut for in your case typing IEnumerable<Holding>.
If you want the result to be List<Holding> then all you need to do is wrap your query in brackets and put .ToList() at the end.
However, to append this to another list, you don't need to do that. Simply call .AddRange on the other list.
Alternatively, you can use Concat
var bothLists = aList.Concat(anotherList);
I would like to replace var unitHld with List unitHld but can't get the code to work.
You need to call ToList() on the result of the query:
var unitHld = from hld in _holdingList
where hld.FundCode == lookThroList[i].FundCode
select new Holding() { Currency = hld.Currency,
FundCode = lookThroList[i].FundCode,
IdSedol = hld.IdSedol,
Nominal = hld.Nominal * unitWgt,
Price = hld.Price };
List<Holding> unitHldList = unitHld.ToList();
This new list is then slightly altered before being added back to the original list
Once the data is in unitHldList, you can alter it as needed.
the line below does not work. _holdingList.Add(unitHld);
When you add the content of a collection to a List<T>, use AddRange method instead of Add:
_holdingList.AddRange(unitHldList);
Try this:
_holdingList.AddRange(unitHld);

Is this loop possible to do using simple LINQ?

I got a class called BG which has a property called Name Code.
I instantiate an object called bgList.
Now I am trying to get all the Code of the objects which have their 'Crop' property set to cropName.
I would like to convert the following working code to linq but for the life of me am unable to do that - am quite sure that I am missing something:
List<string> breedingGroupsAndRoles = new List<string>();
for (int i = 0; i < bgList.Count; i++)
{
if (bgList[i].Crop == cropName)
breedingGroupsAndRoles.Add(bgList.[i].Code);
}
The closest I came was this but it only nets me the first item:
breedingGroupsAndRoles.Add(bgrList.Find(c => c.Crop == cropName).Role);
List<string> breedingGroupsAndRoles = bgList
.Where(bg => bg.Crop == cropName)
.Select(bg => bg.Code)
.ToList();
Just for the sake of completeness, the Find method you tried calling on bgList is not part of LINQ, it's a member of the generic List class itself. It only returns the first element matched by the predicate you provide, which is why you were only getting one result. You probably wanted the FindAll method, which returns a list of all matching elements:
List<BG> breedingGroups = bgList.FindAll(c => c.Crop == cropName);
Note that this produces a list of matching BG instances rather than just their Role properties. Depending on how you're processing the results this may be sufficient, otherwise you'll still need LINQ or a loop and a second list to extract the Role values. In any case, an all-LINQ solution such #Tim Schmelter's is likely the better way to go.

Linq to SQL select multiple columns

I just want to select 2 columns from a MSSQL DB using LINQ.
The SQL should be
select table.col1,table.col2 from table
I tried
IList<string> myResults =
(
from data in dbconn.table
where table.col5 == null
select new {
col1=data.Id.ToString(),
col2=data.col2
}
).Take(20).ToList();
but this didn't work.
It says
cannot convert type list <AnonymousType#1> to Ilist<string>
You are basically trying to fill a list of strings with the entries of a list of anonymous types, that won't work.
Have you tried something like this?:
var list = from data in dbconn.table
where table.col5 == null
select new {
col1=data.Id.ToString(),
col2=data.col2
}
Then you can easily use the entries in a loop for example
foreach(var element in list) {
//...
}
Or like a list
list.Take(20).ToList();
First of all, a list of strings (List<string>) can only have one single string in an element not two (what you are trying to do here) changing the type to var would fix your exception but not sure if that is the solution you want.
var myResults =
(
from data in dbconn.table
where table.col5 == null
select new {
col1=data.Id.ToString(),
col2=data.col2
}
).Take(20).ToList();
You can select multiple fields using linq Select as shown above in various examples this will return as an Anonymous Type. If you want to avoid this anonymous type here is the simple trick.
var items = myResults.Select(f => new [] { f.Col1, f.Col2 }).SelectMany(item => item).Distinct();
I think this solves the problem

Compare two IQueryable instances

I have two IQueryable instances - objIQuerableA and objIQueryableB and I want to obtain only elements that are present in objIQuerableA and not in objIQuerableB.
One way is to use a foreach loop but I wonder if there is a better method.
Simple and straight forward.
var result = objIQuerableA.Except(objIQuerableB);
The title actually says compare two IQueryables. If you wanted to actually do a compare to determine if both IQueryable contain the same results in a single query....
var aExceptB = objIQuerableA.Except(objIQuerableB);
var bExceptA = objIQuerableB.Except(objIQuerableA);
var symmetricDiff = aExceptB.Union(bExceptA);
bool areDifferent = symmetricDiff.Any();

Categories

Resources