LINQ C# complex nesting structure - c#

I managed to make a selection from the complex structure of the object, but only with the help of foreach, how can I avoid this foreach and solve my problem, just using LINQ?
var product = new List<ProductCrp>
{
new ProductCrp {
Strucutre = new StructureItem() {
CheckList = new CheckList() {
Checks = new List<Check>
{
new Check { NumberAsInt = "149" },
new Check { NumberAsInt = "260" },
new Check { NumberAsInt = null }
}
}
}
},
new ProductCrp {
Strucutre = new StructureItem() {
CheckList = new CheckList() {
Checks = new List<Check>
{
new Check { NumberAsInt = "261" },
new Check { NumberAsInt = "150" },
new Check { NumberAsInt = "260" }
}
}
}
}
};
string[] numbers = { "149" };
LINQ:
foreach (var item in product)
{
item.Strucutre.CheckList.Checks = item.Strucutre.CheckList.Checks.Where(w => numbers.Contains(w.NumberAsInt)).Select(w => w);
}

I managed to make a selection from the complex structure of the object, but only with the help of foreach, how can I avoid this foreach and solve my problem, just using LINQ?
You do not use LINQ for this purpose. You are using foreach correctly.
LINQ is for querying data. A foreach loop is about producing a side effect repeatedly. The body of your foreach is mutating a property of an object; that's an update and not a query, so you are doing it right. Using LINQ for that is wrong; don't do it.
Answers that say to, for instance, use ToList to force iteration of a query with a side effect are extremely bad style and result in code which is inefficient, hard to understand, hard to maintain, and works against the purpose of the query operators. NEVER abuse LINQ like that. We have a construct built into the language that means "perform this operation once per collection element", and it is called foreach. Use it.

Are you looking for something like this?
product.ForEach(item => item.Strucutre.CheckList.Checks = item.Strucutre.CheckList.Checks.Where(w => numbers.Contains(w.NumberAsInt)).Select(w => w).ToList());

Related

Comparing attributes from a List inside a List

Description
My goal is to compare the language of a menu object from the menuList. Since the menuList has the Languages offered as another list it makes it a bit more complicated. So I tried to create a new class object with the same values so I can use menuList.Languages.Contains(languageObject), however I quickly found out that this doesn't work like that. I tried to make a for loop inside a for loop which didn't work either, but could be a failure from my side.
Obviously I can't write something like: MenuList.Languages.Name.Equals("English").
Because of that I am looking for a solution where I can check if the attribute Name of the Languages-List inside the menuList equals a value of my choice.
The Object
private LanguageBox LangEng = new LanguageBox
{
IsoCode = "eng",
Name = "English"
};
The List
var MenuList = menuDataClient.GetMenuByCity(city)
.Select(nap => new MenuBox()
{
Menu = nap.Menu,
Languages = nap.Languages
.Select(lang => new LanguageBox()
{
IsoCode = lang.IsoCode,
Name = lang.Name
}).ToList()
})
.ToList();
The Loop
for (int i = 0; i < MenuList.Count; i++)
{
if (MenuList[i].Languages.Contains(LangEng))
{
System.Console.WriteLine("Success");
}
}
Maybe linq's Where could do the trick? Sth like:
foreach(var item in MenuList)
{
var x = item.Languages.Where(obj => obj.Name == <desired language>);
if (x.Count() > 0)
{
//Success code
break;
}
}
I have found a solution. This LINQ option works if you want to only keep elements in the list which have English or Russian in their Languages-List.
Solution
.Where(lang => lang.Languages.Any(any => any.Name.Equals("English") || any.Name.Equals("Russian")))

How to get list items without for each in MVC controller

I need to access items from a list which is i am accessing with the following code
foreach (var reportval in reportresponse)
{
foreach (var valitem in reportval.Comparison)
{
var responsemodel = new ReportResponseModel();
responsemodel.StudentVariable = valitem.StudentVariable;
responsemodel.Lighter = valitem.Lighter;
responsemodel.Matched = valitem.Matched;
responsemodel.Stronger = valitem.Stronger;
reportResponseModel.Add(responsemodel);
}
};
I tried the following code to exit the loop without retiterting the first loop. But its not working.
if (reportresponse.Count == reportResponseModel.Count) { break; };
also i tried the following way to access the inner list from the first loop but its not accessible here
foreach (var reportval in reportresponse.Comparison)
Can someone please help on this?
Did you try like this
foreach (var reportval in reportresponse.Comparison)
{
// var responsemodel = new ReportResponseModel();
responsemodel.StudentVariable = valitem.StudentVariable;
responsemodel.Lighter = reportval .Lighter;
responsemodel.Matched = reportval .Matched;
responsemodel.Stronger = reportval .Stronger;
//reportResponseModel.Add(responsemodel);
}
};
Have you tried Linq's SelectMany?
You can do something like
var reportResponseModel = reportresponse.SelectMany(r => r.Comparison, (r, c) =>
new ReportResponseModel
{
StudentVariable = c.StudentVariable,
Lighter = c.Lighter,
Matched = c.Matched,
Stronger = c.Stronger
});
Then you can apply additional filtering like with .Where or .Take to have only needed count of items.
I updated the code with the following changes.
if (reportresponse.Count == reportResponseModel.Count)
{ return reportResponseModel; };
after
reportResponseModel.Add(responsemodel);
Thanks #Stephen Muecke !!

Correct way of Dictionary in a Dictionary Value?

I would like to know the most optimal/elegant solution of doing this. Basically i have 3 groups of data.
Each of the groups are inside another in a hierarchy. I'm using a dictionary within a dictionary to achieve this. Sample Code:
Dictionary<string,Dictionary<string,List<string>>> pro = new Dictionary<string,Dictionary<string,List<string>>>();
Dictionary<string,List<string>> part = new Dictionary<string,List<string>>();
List<string> foo = new List<string>();
List<string> bar = new List<string>();
foo.Add("foo1");
foo.Add("foo2");
foo.Add("foo3");
bar.Add("bar1");
bar.Add("bar2");
bar.Add("bar3");
part.Add("Part1", foo);
part.Add("Part2", bar);
pro.Add("First", part);
foreach (var pros in pro)
{
foreach (var parts in pros.Value)
{
foreach (var foos in parts.Value)
{
Console.WriteLine(foos);
}
}
}
I'm still new to c#, even though my code is working i still feel that there is a more elegant solution. Thanks in advance!
I think you should refactor this kind of code into simple wrapper-classes of Dictionaries. It's almost unreadable this way but if you make a wrapper-class for Parts/Pros, whatever your names are you get niecer looking and reading code and can put some utility functions inside the classes while hiding the implementation-detail of using Dictionaries.
you could use collection initializers for the construction part and LINQ for the print part.
Dictionary<string, Dictionary<string,List<string>>> pro = new Dictionary<string, Dictionary<string,List<string>>>()
{
{ "First", new Dictionary<string,List<string>>()
{
{ "Part1", new List<string>() { "foo1", "foo2", "foo3" } },
{ "Part2", new List<string>() { "bar1", "bar2", "bar3" } }
}
}
};
EDIT: provided new link for LINQ referring to another useful related post on stackoverflow.

programmatically navigate a linq to sql result

I have the following....
var jobsApplications = ( from applications in db.applications
where applications.employeeId == LogedUser.Id
select new { applications.id, applications.jobId, applications.confirmationDate });
Now I want to navigate this result like
foreach "something" in jobsApplications
But I don't now what to put in something since the select new create a new class.
Any suggestions
I guess you can let the compiler do the work for you:
foreach (var application in jobApplications)
{
// use the application wisely
}
Consider using Array.ForEach() to iterate through your IEnumerable or List. This is a bit more heavyweight.
Array.ForEach(jobsApplication, jobApp => {
if (jobApp.City == "Chicago")
{
jobApp.Approved = true;
}
});
If you want a simple foreach, then you can type the anonymous class as var
foreach (var jobApp in jobApplications)
{
if (jobApp.City == "Chicago")
{
jobApp.Approved = true;
}
}

What's the pattern to use for iterating over associated sets of values?

It's pretty common - especially as you try to make your code become more data-driven - to need to iterate over associated collections. For instance, I just finished writing a piece of code that looks like this:
string[] entTypes = {"DOC", "CON", "BAL"};
string[] dateFields = {"DocDate", "ConUserDate", "BalDate"};
Debug.Assert(entTypes.Length == dateFields.Length);
for (int i=0; i<entTypes.Length; i++)
{
string entType = entTypes[i];
string dateField = dateFields[i];
// do stuff with the associated entType and dateField
}
In Python, I'd write something like:
items = [("DOC", "DocDate"), ("CON", "ConUserDate"), ("BAL", "BalDate")]
for (entType, dateField) in items:
# do stuff with the associated entType and dateField
I don't need to declare parallel arrays, I don't need to assert that my arrays are the same length, I don't need to use an index to get the items out.
I feel like there's a way of doing this in C# using LINQ, but I can't figure out what it might be. Is there some easy method of iterating across multiple associated collections?
Edit:
This is a little better, I think - at least, in the case where I have the luxury of zipping the collections manually at declaration, and where all the collections contain objects of the same type:
List<string[]> items = new List<string[]>
{
new [] {"DOC", "DocDate"},
new [] {"CON", "ConUserDate"},
new [] {"SCH", "SchDate"}
};
foreach (string[] item in items)
{
Debug.Assert(item.Length == 2);
string entType = item[0];
string dateField = item[1];
// do stuff with the associated entType and dateField
}
In .NET 4.0 they're adding a "Zip" extension method to IEnumerable, so your code could look something like:
foreach (var item in entTypes.Zip(dateFields,
(entType, dateField) => new { entType, dateField }))
{
// do stuff with item.entType and item.dateField
}
For now I think the easiest thing to do is leave it as a for loop. There are tricks whereby you can reference the "other" array (by using the overload of Select() that provides an index, for example) but none of them are as clean as a simple for iterator.
Here's a blog post about Zip as well as a way to implement it yourself. Should get you going in the meantime.
Create a struct?
struct Item
{
string entityType;
string dateField;
}
Pretty much the same as your Pythonic solution, except type-safe.
This is realy a variation on the other themes, but this would do the trick also...
var items = new[]
{
new { entType = "DOC", dataField = "DocDate" },
new { entType = "CON", dataField = "ConUserData" },
new { entType = "BAL", dataField = "BalDate" }
};
foreach (var item in items)
{
// do stuff with your items
Console.WriteLine("entType: {0}, dataField {1}", item.entType, item.dataField);
}
You can use the pair and a generic List.
List<Pair> list = new List<Pair>();
list.Add(new Pair("DOC", "DocDate"));
list.Add(new Pair("CON", "ConUserDate"));
list.Add(new Pair("BAL", "BalDate"));
foreach (var item in list)
{
string entType = item.First as string;
string dateField = item.Second as string;
// DO STUFF
}
Pair is part of the Web.UI, but you can easily create your own custom class or struct.
If you just want to declare the lists inline, you can do that in one step:
var entities = new Dictionary<string, string>() {
{ "DOC", "DocDate" },
{ "CON", "ConUserDate" },
{ "BAL", "BalDate" },
};
foreach (var kvp in entities) {
// do stuff with kvp.Key and kvp.Value
}
If they're coming from other things, we have a bunch of extension methods to build dictionaries from various data structures.

Categories

Resources