Getting a List<Items> out of List<List<Items>> - c#

I have a object called Items. I use that object like so.
List<List<Items>> myItems = new List<List<Items>>();
I want to know how to get a specific List<Items> out of the List<List<Items>> object. Currently I am using foreach loops with some rules to find a specific List<Items>
This is currently what I am doing
foreach (List<Items> db2Items in db2Data)
{
foreach (List<Items> apiItems in apiData)
{
if (db2Items[0].Value == apiItems[0].Value && db2Items[27].Value == apiItems[27].Value)
{
/// Some other logic here
}
}
}
I was wanting to use LINQ to get the matching List<items> out of apiData and if I have a result then do the logic I wanted to do.

Not really sure what you're trying to accomplish, but if you want to get a list in a list based on a certain condition you can do it like this:
var item = db2Data.Where(x => x.Where(y => y.[value] == [YourCondition]).Any()).FirstOrDefault();
the "x.Where(y => y == [YourCondition]).Any()" will return true if the condition is met, and firstordefault will then return the list that meets the condition.

I have figured it out.
Using LINQ:
foreach (List<Items> db2Items in db2Data)
{
IEnumerable<List<Items>> theItem = from item in apiData
where item[0].Value == db2Items[0].Value && item[27]>Value == db2Items[27].Value
select item;
if (theItem.ToList().Count > 0)
{
// Do something
}
}

Related

Iterate over an IQueryable without calling ToList()

I have a DB used for a production line. It has an Orders table, and Ordertracker table, an Item table, and an Itemtracker table.
Both Orders and Items have many-to-many relationships with status. The tracker tables resolves these relationships in such a way that an item can have multiple entries in the tracker - each with a particular status.
I tried to upload a picture of the tables to make things clearer but alas, I don't have enough points yet :C
I need to find items whose last status in the Itemtracker table meets a condition, either '3' or '0'.
I then need to get the first one of these items.
The steps I am using to accomplish this are as follows:
Get all the Orders which have a certain status.
Get all the Items in that Order.
Get all the Items whose last status was = 0 or 3.
Get the first of these items.
My code is as follows:
public ITEM GetFirstItemFailedOrNotInProductionFromCurrentOrder()
{
var firstOrder = GetFirstOrderInProductionAndNotCompleted();
var items = ERPContext.ITEM.Where(i => i.OrderID == firstOrder.OrderID) as IQueryable<ITEM>;
if (CheckStatusOfItems(items) != null)
{
var nextItem = CheckStatusOfItems(items);
return nextItem ;
}
else
{
return null;
}
}
private ITEM CheckStatusOfItems(IQueryable<ITEM> items)
{
List<ITEM> listOfItemsToProduce = new List<ITEM>();
foreach (ITEM item in items.ToList())
{
var lastStatusOfItem = ERPContext.ITEMTRACKER.Where(it => it.ItemID == item.ItemID)
.OrderByDescending(it => it.ItemTrackerID).FirstOrDefault();
if (lastStatusOfItem.ItemStatus == (int)ItemStatus.Failed || lastStatusOfItem.ItemStatus == (int)ItemStatus.Confirmed)
{
listOfItemsToProduce.Add(item);
}
}
return listOfItemsToProduce.FirstOrDefault();
}
Now, this all works fine and returns what I need but I'm aware that this might not be the best approach. As it is now my IQueryable collection of items will never contain more than 6 items - but if it could grow larger, then calling ToList() on the IQueryable and iterating over the results in-memory would probably not be a good idea.
Is there a better way to iterate through the IQueryable items to fetch out the items that have a certain status as their latest status without calling ToList() and foreaching through the results?
Any advice would be much appreciated.
Using LINQ query syntax, you can build declaratively a single query pretty much the same way you wrote the imperative iteration. foreach translates to from, var to let and if to where:
private ITEM CheckStatusOfItems(IQueryable<ITEM> items)
{
var query =
from item in items
let lastStatusOfItem = ERPContext.ITEMTRACKER
.Where(it => it.ItemID == item.ItemID)
.OrderByDescending(it => it.ItemTrackerID)
.FirstOrDefault()
where (lastStatusOfItem.ItemStatus == (int)ItemStatus.Failed || lastStatusOfItem.ItemStatus == (int)ItemStatus.Confirmed)
select item;
return query.FirstOrDefault();
}
or alternatively using from instead of let and Take(1) instead of FirstOrDefault():
private ITEM CheckStatusOfItems(IQueryable<ITEM> items)
{
var query =
from item in items
from lastStatusOfItem in ERPContext.ITEMTRACKER
.Where(it => it.ItemID == item.ItemID)
.OrderByDescending(it => it.ItemTrackerID)
.Take(1)
where (lastStatusOfItem.ItemStatus == (int)ItemStatus.Failed || lastStatusOfItem.ItemStatus == (int)ItemStatus.Confirmed)
select item;
return query.FirstOrDefault();
}

C# using aggregate method on nopcommerce shipment items list not working

Ok so I'm trying to get all items which have been shipped and add them to a list if the shipment item is not already in that list. But if the shipment item is found in the list then I want to combine those two items in the list.
Here is the code I'm working with:
var shippedItems = _orderService.GetOrderById(shipment.OrderId).Shipments.Where(x => x.ShippedDateUtc != null && x.OrderId == shipment.OrderId && x.Id != shipment.Id).ToList();
List<ShipmentItem> shipmentItemsList = new List<ShipmentItem>();
for (int i = 0; i <= shippedItems.Count - 1; i++)
{
var si = shippedItems[i];
var sii = si.ShipmentItems.ToList();
foreach (var item in sii)
{
if (!shipmentItemsList.Contains(item))
{
shipmentItemsList.Add(item);
}
else
{
var foundId = shipmentItemsList.Select(x => x.Id == item.Id);
shipmentItemsList.Aggregate((foundId, item) => foundId + item);
}
}
}
For these two variables (foundId, item) i get errors:
A local variable named the variable name cannot be declared in this
scope because that name is used in an enclosing local scope to define
a local or parameter
UPDATE
I also thought I could try the following, but it's not joining the results.
if (i == 0)
{
shipmentItemsList = si.ShipmentItems.ToList();
}
else
{
shipmentItemsList.Concat(si.ShipmentItems.ToList());
}
Anyone able to point me on the right track.
Cheers
Thanks for the clarification. Essentially, the way that I understand your problem is that you need to take an object map that is grouped by Shipment and look at it from the point of Item instead. Linq can deal with this for you by using SelectMany to flatten the list and the GroupBy to shape the flattened list into your new groupings. I've made some assumptions about property names for the nopCommerce objects, but the following code sample should get you close enough to tweak with the correct property names:
var shipmentItemsList = shippedItems // This is logically grouped by shipment id
.SelectMany(s => s.ShipmentItems) // First flatten the list
.GroupBy(i => i.ItemId) // Now group it by item id
.Select(g => new
{
ItemId = g.Key,
Quantity = g.Sum(item => item.Quantity)
}) // now get the quantity for each group
.ToList();

Search based off a changing list of parameters

I have a list of these objects:
public class seat
{
public String id, tooltip;
public String Section, Row, Number;
public Boolean Taken;
}
I would like to build a function to search the elements of the class. However, I will not always be searching for all of the elements.
I know I could do this with a loop, and some if-statements. Saying something along the lines of
public ArrayList searchArray(String section, String row, String number)
{
ArrayList searched = new ArrayList();
foreach(seat item in seats)//seats is a list of the seat class
{
if(section!="" && row!=""&& id!="")
{
if(item.Section==section && item.Row==row &&item.id==id)
searched.Add(item);
}
else if(section!="" && row!="")
{
if(item.Section==section && item.Row==row)
searched.Add(item);
}
else if(row!="")
{
if(item.Row==row)
searched.Add(item);
}
/////Continue this for all the other combinations of searching
}
return searched;
}
I could also to it several loops like
if(Section!="")
foreach(seat item in seats)
if(item.Section==section)
searched.Add(item);
seats = searched;
search.Clear();
if(id!="")
foreach(seat item in seats)
if(item.id==id)
searched.Add(item);
seats = searched;
search.Clear();
if(row!="")
foreach(seat item in seats)
if(item.Row==row)
searched.Add(item);
So first one is tedious and requires a lot of ugly code.
The second is a little better, but requires I go through the list more than once. More specifically it requires me to go through the list for each parameter I am looking for.
Is there a way I can do this where you just add the parameters you want to look for and then search. Sort of like you generate an sql query to search.
Less important, but would be amazing if it could work, would be to even allow ranges for the search. Like id>2 && id<12
This is where IEnumerable<> is your friend!
IEnumerable<seat> query = seats.AsEnumerable();
if(!string.IsNullOrEmpty(section))
query = query.Where(s => s.Section == section);
if(!string.IsNullOrEmpty(row))
query = query.Where(s => s.Row == row);
if(!string.IsNullOrEmpty(id))
query = query.Where(s => s.Id == id);
List<seat> results = query.ToList(); // deferred execution
ArrayList searched = new ArrayList(
seats.Where(c => c.Section == section && !string.IsNullOrEmpty(section))
.Where(c => c.Row == row && !string.IsNullOrEmpty(row))
.Where(c => c.id == id && !string.IsNullOrEmpty(id)).ToList());

Is there a faster way to do this LINQ?

I have a loop inside my program, which loops through thousands of object to find the right one with particular id.
is there any better and faster way than this
int id;
SPList list = SPContext.Current.Web.Lists.TryGetList("DataLibrary");
IEnumerable<SPListItem> _dataitems = list.Items.OfType<SPListItem>();
foreach (SPListItem item in _dataextantitems)
{
if (item.ID == id)
{
title= item.Title;
}
}
Use the GetItemById of SPList.
var title = SPContext.Current.Web.Lists["DataLibrary"].GetItemById(id).Title;
If your list has a lot of columns, and you want to avoid pulling them all down, you can pull down just the Title column instead:
var title = SPContext.Current.Web.Lists["DataLibrary"]
.GetItemByIdSelectedFields(id, "Title").Title;
Now if you really want to use LINQ here you could use LINQ to Sharepoint, but it's not actually going to simplify the code a ton. After using SPMetal.exe to generate a file based on your lists, you'd be able to write:
using(var context = new YourContextNameHere(SPContext.Current.Site.Url))
{
var title = context.DataLibrary
.Where(item => item.ID == id)
.Select(item => item.Title)//to avoid pulling down other columns
.First();
}
Make sure your list is sorted. Then you can use the BinarySearch method of the list or write your own implementation. If not you can shorten your code using linq.
var itemToLookup = list.Items.OfType<SPListItem>().FirstOrDefault(x => x.ID == id);
if (itemToLookup != null)
{
//...
}

select from list which has same code

I have a problem in getting the values for the below.
I have a table called Retailers which contains Id,Description,Language and Code
I declared a list in my application which contains all the retailers list
var retailers = new List<Retailer>();
Now I need to add results of two retailers with same code so I am trying to do below and I am sure I am doing something wrong.
foreach (var retailer in retailers)
{
if (retailer.LanguageId != null)
{
// Here I am trying to findout if there are any other retailers who
// has same code if true then I need entire row of that retailer
**var retailerWithSameUacode = !retailers.Select(item => item.Code == retailerCode).SingleOrDefault();**
if (retailerWithSameUacode != null)
{
// Do something
}
}
}
Any help is much appreciated !
I don't think I entirely understand your question, but from your code comment and your attempt to select a retailer with the same code, I present to you the following..
To get the first retailer out of your list with a code that matches the current retailer, you would need to do this:
Retailer retailerWithMatchingCode = retailers.Where(r => r.Code == retailer.Code).FirstOrDefault();
You can then check the retailerWithMatchingCode object for a null value. If you just want to know if a retailer with a matching code exists, this is what you would do:
if (retailers.Any(r => r.Code == retailer.Code))
//Do something..
To get a list of retailers who have a matching "Code" property value, you would need to do this:
List<Retailer> retailersWithMatchingCode = retailers.Where(r => r.Code == retailer.Code).ToList();
Please note that this code is untested.
Try this solution:
var retailerWithSameUacode = retailers
.Where(item => item.LanguageId != null && item.Code == retailerCode)
.ToList();
foreach (var item in retailerWithSameUacode)
{
// Do something
}

Categories

Resources