Lambda inside if statement? - c#

How can I use lambda inside an if statement to compare a treenode's value to an object value inside a list ? Currently I am trying something like this but it won't work. Is there any better way to simplify my search?
if (tvItems.Nodes.Count > 0)
{
// Get checked items
listChecked= MenuItemDTOManager.GetMenuItems();
//
foreach (TreeNode parentNode in tvItems.Nodes)
{
if (listChecked.Find(s => s.menuId.ToString() == parentNode.Value.ToString()))
{
parentNode.Checked = true;
}
}
// Traverse children
}

Should be using Any instead of Find:
if (listChecked.Any(s => s.menuId.ToString() == parentNode.Value.ToString()))
{
parentNode.Checked = true;
}

if requires a bool value only.
listChecked.Find(s => s.menuId.ToString() == parentNode.Value.ToString())
Find won't return bool.
Try using Exists instead of Find.

Probably you are looking for the following.
foreach (TreeNode parentNode in tvItems.Nodes.OfType<TreeNode>().Any(n=> listChecked.Any(s => s.menuId.ToString() == n.Value.ToString()))
{
parentNode.Checked = true;
}

Related

Is it possible to convert this foreach loop into a LINQ-to-XML loop?

I originally asked this question (Can we automatically add a child element to an XElement in a sortable manner?) and it was closed as a duplicate (how to add XElement in specific location in XML Document).
This is teh code that I have at the moment:
bool bInserted = false;
foreach (var weekDB in xdoc.Root.Elements())
{
DateTime datWeekDB = DateTime.ParseExact(weekDB.Name.LocalName, "WyyyyMMdd", CultureInfo.InvariantCulture);
if (datWeekDB != null && datWeekDB.Date > historyWeek.Week.Date)
{
// Insert here
weekDB.AddBeforeSelf(xmlHistoryWeek);
bInserted = true;
break;
}
}
if (!bInserted)
xdoc.Root.Add(xmlHistoryWeek);
It works fine. But I wondered if I can use LINQ to acheive the same thing? The linked answer suggests:
Search element you want to add and use Add method as shown below
xDoc.Element("content")
.Elements("item")
.Where(item => item.Attribute("id").Value == "2").FirstOrDefault()
.AddAfterSelf(new XElement("item", "C", new XAttribute("id", "3")));
But I don't understand how to end up with logic like that based on my codes logic.
I think the best way to think about it is: you are going to use LINQ to find a specific element. Then you will insert into the document based on what you found.
So something like this:
var targetElement = xdoc.Root.Elements()
.Where(weekDB => {
DateTime datWeekDB = DateTime.ParseExact(weekDB.Name.LocalName, "WyyyyMMdd", CultureInfo.InvariantCulture);
return datWeekDB != null && datWeekDB.Date > historyWeek.Week.Date;
})
.FirstOrDefault();
if (targetElement == null)
{
xdoc.Root.Add(xmlHistoryWeek);
}
else
{
targetElement.AddBeforeSelf(xmlHistoryWeek);
}

Algorithm to implement a JOIN with some limitation

Let me explain my matching problem with a real example (the problem is generic). Assume having 2 lists: of "selections" loaded from different sources. The list don't have duplicates.
Let's say mkTPL.Selections and mkDB.Selections come from SQL Tables each with an unique index on the id and the selection's name. The problem is that sometimes IdSelectionType is null (in the selection from mkTPL.Selections)
foreach (var selTPL in mkTPL.Selections)
{
foreach (var selDB in mkDB.Selections)
{
if (selTPL.IsTheSame(selDB))
selTPL.OddOrResultValue = selDB.OddOrResultValue;
}
}
public bool IsStessaSelezione(SelectionPrints selDb)
{
if (selDb.IdSelectionType == this.IdSelectionType)
return true;
else
{
bool isSameName = selDb.Name == this.Name;
bool isSimilarName = false;
if (!isSameName)
{
isSimilarName = RegexReplace(selDb.Name, #"\([\d.]+\)") == RegexReplace(this.Name, #"\([\d.]+\)");
}
return isSameName || isSimilarName;
}
}
The match alghtoritm that I have implemented is not efficient. Once a selection is matched I shouldn't try to match it further with others (because of the unique index on the id and on the selection name).
Linq could provide me an easy solution?
First of all, you should break when you found a match:
foreach (var selTPL in mkTPL.Selections)
{
foreach (var selDB in mkDB.Selections)
{
if (selTPL.IsTheSame(selDB))
{
selTPL.OddOrResultValue = selDB.OddOrResultValue;
break; // <--
}
}
}
Second, I would make a dictionary of mkDB.Selections, where you store the regexed value so you don't have to make that calculation over and over again, on every iteration.
Something like:
var mkDBDictionary = mkDB.Selections.ToDictionary(s => RegexReplace(s.Name, #"\([\d.]+\)"), s => s);
foreach (var selTPL in mkTPL.Selections)
{
string selTPLName = RegexReplace(selTPL.Name, #"\([\d.]+\)");
if (mkDBDictionary.TryGetValue(selTPLName, out var selDB))
{
selTPL.OddOrResultValue = selDB.OddOrResultValue;
}
}

is there a way to set a variable to something at the end of foreach loop if condition not met in C#?

foreach (Objecta a in aList())
{
foreach (Objectb b in bList)
{
if (a.variable != b.variable1 && a.variable() != b.variable2)
{
a.setVariable("Error");
}
}
}
The problem I am getting is that it goes through the foreach loop the first time and it sets variable to error without checking if other values (when it goes through the loop again) finds a match.
What I would like is to wait until it goes through all the lists and at the last foreach loop iteration if nothing in aList matches the variable target && variable source in bList then finally set it to Error flag.
Any suggestions to get around this will be appreciated.
Try doing it the other way around. Search for a match instead of searching for non-matches.
foreach (Objecta a in aList())
{
bool foundMatch = false;
foreach (Objectb b in bList)
{
if (a.variable == b.variable1 || a.variable() == b.variable2)
{
foundMatch = true;
break;
}
}
if (!foundMatch)
{
a.setVariable("Error");
}
}
I think this is what you are looking for. So if StoreList is the outer loop and LinkList is the inner loop. You want to search all the links to see if there's an ID that matches the store ID. If you find a match, stop searching the links. After the search through the links, set an error on the store if there was no match, then go to the next store.
foreach (Objecta a in aList())
{
var foundMatch = false;
foreach (Objectb b in bList)
{
if (a.variable == b.variable1 || a.variable() == b.variable2)
{
fondMatch = true;
break;
}
}
if (!foundMatch) a.setVariable("Error");
}
I think you want something like this:
First select all the item values from aList and bList and put them in a seperate array:
var aVals = aList.Select(x=>x.value1).ToArray();
var bListVals1 = bItems.Select(x=>x.value1).ToArray();
var bListVals2 = bItems.Select(x=>x.value2).ToArray();
var bVals = bListVals1.Concat(bListVals2);
Then, get the values both lists have in common:
var correctVals = bVals.Intersect(aVals);
These are the correct values and so all the other values are wrong:
var wrongVals = aVals.Except(correctVals);
Now you have the values that are wrong and can act accordingly:
wrongAItems = aList.Where(a => wrongVals.Contains(a.value));
foreach(wrongA in wrongAItems){
wrongA.setVariable("Error");
}
foreach (Store s in processFlowStores.getStoresList())
{
if (!processFlowLinks.Any(l => s.getNodeId() == l.getLinkSource() ||
s.getNodeId() == l.getLinkTarget()))
{
s.setID("Error: FailedOperation Error - 123.123.121");
}
}
EDIT: more compact solution using Linq. Basically, if none of the links has it as either source or target, mark it as error.

if statement on a foreach

I notice i do this pattern a lot. Is there a better way to write this?
bool hit=false;
foreach (var tag in tags)
if (tag == sz)
{
hit = true;
break;
}
if (hit) continue;
//tags.add(sz); or whatever i wanted to do
I know if sz in tags exist in other languages. I hope theres something in linq that can help?
For the example:
if (tags.Contains(sz)) ...
For the more general problem:
if (tags.Any(tag => InvolvedLogic(tag))) ...
Assuming tags is a List<T>:
if (tags.Contains(sz))
{
// ...
}
If you just want to know if a given item is in tags, do:
if(tags.Any(t => t == sz))
{
// Do stuff here
}
If you want to grab a reference to the found item, do:
var foundTag = tags.FirstOrDefault(t => t == sz);
// foundTag is either the first tag matching the predicate,
// or the default value of your tag type
if (tags.Any(t=>t == sz) == true)
{
//...
}

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;
}
}

Categories

Resources