Please check Part1 carefully. The variable "singleItem" containing the item during loop of each Ids. But my goal is convert this "singleItem" variable as a List of items. So i can use this "singleItem" in another method like Part2
Part1:
foreach (int Id in Ids)
{
var singleItem = ctx.SingleScannedItems.FirstOrDefault(x => x.SingleScannedItemId == Id);
}
Part2:
public string MyMethod(List<singleItem> items)
{
//do something with items
}
You can use Contains method to query all the items which has SingleScannedItemId property value matching to the values in the Ids collection.
var filteredItems = ctx.SingleScannedItems
.Where(x => Ids.Contains(x.SingleScannedItemId)).ToList();
You do not need the loop now as you are querying all those items you wanted once.
The variable filteredItems will be a list of SingleScannedItem. You can pass that to a method which accepts the collection.
You dont need loop , checking against a Ids list the following would work.
List<singleItem> items = ctx.SingleScannedItems
.Where(x => Ids.Contains(x.SingleScannedItemId).ToList();
MyMethod(items);
Related
I have a 2D nested list List<list<dynamic>>, I'd like to get first elements of every second level list and form a new List<dynamic>.
I know .first() gets the first element of a list, but how can I apply it on multiple sub lists?
Thanks in advance.
Proper and efficient way of doing this is as follows:
mainList.Select(subList => subList?.First()).OfType<dynamic>();
This will take care of null lists and null elements
If you want to select all the elements of sublists try following
mainlist.Select(subList => subList).OfType<List<dynamic>>();
This will only take care of null lists
IEnumerable s = listOfLists.Where(lists => lists.Any())
.Select(array => array.First());
Explanation:
First fetch the list of arrays where there are any records by using lists => lists.Any()
Then select the first item from each list and return.
try this please if you want to take the first two elements of each list, and the more elements you want you can increase the integer in the .Take().
List<List<string>> originalList = new List<List<string>>()
{
new List<string>(){"1","1","1"},
new List<string>(){"2","2"},
};
var FirtTwoElementsList = originalList.Select(x => x.Take(2)).ToList();
List<string> FinalList = new List<string>();
foreach (var item in FirtTwoElementsList)
{
FinalList.AddRange(item.ToList<string>());
}
I have this code:
HashSet<string> MyHash = new HashSet<String>();
foreach (MyType a in myCollection)
{
foreach (string b in a.mylist)
{
MyHash.Add(b);
}
}
I tried to make it easier to read like this but it doesn't work:
myCollection.MyType.select(x => x.mylist.select(y => MyHash.add(y)));
Any suggestions?
Select will return a collection of items instead of modifying it. Thus you have to assign its return-value into a variable or member or pass it into a method. Furthermore you´d need to flatten the results to add the members of your inner list into the hashset.
Thus when you want to add the result into your list use HashSet.UnionWith:
myHash.UnionWith(myCollection.SelectMany(x => x.MyList));
Alternativly you can also use the constructor of HashSet that accepts a collection of items:
var myHash = new HashSet<string>(...);
However IMHO this isn´t any more readable than using some foreach-based approach.
Here's how I would do it, separating query definition and state modification.
IEnumerable<string> items = myCollection.SelectMany(a => a.myList);
foreach(string b in items)
{
MyHash.Add(b);
}
If you want to one-line it for some reason:
myCollection.SelectMany(a => a.myList).ToList().ForEach(b => MyHash.Add(b));
why cant I select remove or delete? I want to remove a record from a list
IEnumerable<StockLocation_Table> AllCurrentStocklocations = db.StockLocation_Table.ToList();
List<StockLocation> StockLocations = ServerHelper.GetStockLocationsBatch(BatchUrl, i, batchSize);
foreach (StockLocation_Table _stock_table in AllCurrentStocklocations)
{
foreach (StockLocation _stock in StockLocations)
{
if (_stock.ServerLocationId == _stock_table.ServerLocationId)
{
AllCurrentStocklocations.?? why cant i say remove._stock_table
}
}
}
Because it is IEnumerable<T> and the Remove method is not defined in IEnumerable<T>.Since you are using ToList just use a List<T> as type:
List<StockLocation_Table> AllCurrentStocklocations = db.StockLocation_Table.ToList();
Edit: Also you can't modify the collection inside of foreach loop.You can use LINQ instead:
var AllCurrentStocklocations = db.StockLocation_Table
.Where(x => !StockLocations
.Any(s => s.ServerLocationId == x.ServerLocationId).ToList()
What you want to do here is get all of the items from your DB table where the ID is not in this other list. What you should do here is construct a query such that you get just those items without those IDs, rather than pulling down the entire DB table into a list, and then going through this other list for each item) to look for IDs so that you can remove the current item from this list. In addition to being super inefficient, this would also mean removing the item from a collection being iterated, which would break the iterator. Instead write something that can be translated into a DB query:
List<StockLocation> stockLocations = ServerHelper.GetStockLocationsBatch(
BatchUrl, i, batchSize);
var locationIDs = stockLocations.Select(location => location.ServerLocationId);
db.StockLocation_Table.Where(item =>
!locationIDs.Contains(item.ServerLocationId));
I am trying to convert the following code to LINQ
foreach (var item in pageHistorycol)
{
if (item.PageTitle.Contains(text) || item.PageURI.Contains(text))
{
tempHistory.Insert(0, item);
}
}
The following returns all items instead of the matches
var matches = pageHistorycol.Where(item =>
(item.PageTitle.Contains(text) || item.PageURI.Contains(text)));
What am I missing?
The two statements you displayed should return the same items. If the second returns all items, the foreach loop should add all of the items to tempHistory as well.
The main difference will be your foreach loop will return the items in the opposite order as your LINQ query. If the order of matches is important, you can get the items in the same order using:
var matches = pageHistorycol
.Where(item => item.PageTitle.Contains(text) || item.PageURI.Contains(text))
.Reverse();
I have an IList<Price> SelectedPrices. I also have an IEnumerable<Price> that gets retrieved at a later date. I would like to add everything from the latter to the former where the former does NOT contain the primary key defined in the latter. So for instance:
IList<Price> contains Price.ID = 1, Price.ID = 2, and IEnumerable<Price> contains Price.ID = 2, Price.ID = 3, and Price.ID = 4. What's the easiest way to use a lambda to add those items so that I end up with the IList containing 4 unique Prices? I know I have to call ToList() on the IList to get access to the AddRange() method so that I can add multiple items at once, but how do I select only the items that DON'T exist in that list from the enumerable?
I know I have to call ToList() on the IList to get access to the AddRange() method
This is actually not safe. This will create a new List<T>, so you won't add the items to your original IList<T>. You'll need to add them one at a time.
The simplest option is just to loop and use a contains:
var itemsToAdd = enumerablePrices.Where(p => !SelectedPrices.Any(sel => sel.ID == p.ID));
foreach(var item in itemsToAdd)
{
SelectedPrices.Add(item);
}
However, this is going to be quadratic in nature, so if the collections are very large, it may be slow. Depending on how large the collections are, it might actually be better to build a set of the IDs in advance:
var existing = new HashSet<int>(SelectedPrices.Select(p => p.ID));
var itemsToAdd = enumerablePrices.Where(p => !existing.Contains(p.ID));
foreach(var item in itemsToAdd)
{
SelectedPrices.Add(item);
}
This will prevent the routine from going quadratic if your collection (SelectedPrices) is large.
You can try that:
var newPrices = prices.Where(p => !SelectedPrices.Any(sp => sp.ID == p.ID));
foreach(var p in newPrices)
SelectedPrices.Add(p);
I know I have to call ToList() on the IList to get access to the AddRange() method so that I can add multiple items at once
ToList will create a new instance of List<Price>, so you will be modifying another list, not the original one... No, you need to add the items one by one.
Try yourEnumerable.Where(x => !yourList.Any(y => y.ID == x.ID)) for the selection part of your question.
If you want to add new elements to the existing list and do that in a most performant way you should probably do it in a conventional way. Like this:
IList<Price> selectedPrices = ...;
IEnumerable<Price> additionalPrices = ...;
IDictionary<int, Price> pricesById = new Dictionary<int, Price>();
foreach (var price in selectedPrices)
{
pricesById.Add(price.Id, price);
}
foreach (var price in additionalPrices)
{
if (!pricesById.ContainsKey(price.Id))
{
selectedPrices.Add(price);
}
}