How to find last occurrence of an element using FindLast() - c#

I want to find the last occurrence of an element in a list and know I must use the FindLast() to do that. However, I don't know how to implement and use this method.
Here is the code that I have:
// the list I need to check
orderedMetricsByNS = (List<Metric>) lmresponse.Metrics.OrderBy(metric => metric.Namespace);
foreach (Metric m in orderedMetricsByNS)
{
// want to use the FindLast() here
}
How do I retrieve the last occurrence of a metric like this? Thanks

What is the Predicate? You can use it like this:
var item = orderedMetricsByNS.FindLast(m => /* your condition */);
Or if you wanna just find the last item use Last method
var item = orderedMetricsByNS.Last();
Btw you can't cast from IOrderedEnumerable<T> to List<T>, your code will fail, you need to use ToList method.
orderedMetricsByNS = lmresponse.Metrics.OrderBy(metric => metric.Namespace).ToList();

You can use LINQ:
var last = orderedMetricByNS.LastOrDefault();
http://msdn.microsoft.com/en-us/library/system.linq.enumerable.lastordefault%28v=vs.95%29.aspx

Related

How to compare ItemElements of a Radcombobox with an expected string?

I need compare if a Radcombobox has ItemElements that matches with my expected string. Here is what I'm trying to do:
foreach (IRadComboBoxItem item in comboBox.ItemElements)
{
var itemExists = comboBox.ItemElements.FirstOrDefault(items => item.Text.Contains(expectedString));
if (itemExists == null) continue;
itemExists.Select();
return true;
}
However comboBox.Text.Contains(expectedString) is not supported as I'm comparing IRadComboBoxItem with a string. Could you please suggest how to achieve this?
Use linq method of Any:
return comboBox.ItemElements.Any(item => item.Text.Contains(expectedString));
In your above code you mixed a bit the use of different linq methods
In the FirstOrDefault - it returns the first item in a collection that matches a predicate, otherwise default(T).
Then if it is not null you perform an Select but assign it to nowhere.
You have this code in a foreach loop - but do not use the item nowhere. you don't need the loop because you are trying to use the linq methods (which behind the scenes use the loops themselves)
Following comment what you want is:
var wantedItem = comboBox.ItemElements.FirstOrDefault(item => item.Text.Contains(expectedString));
if(wantedItem != null)
{
//What you want to do with item
}
Didn't work with RadComboBox myself but by this site maybe:
RadComboBoxItem item = comboBox.FindItemByText(expectedString);
I assume that if it doesn't find it returns null

Function to linq conversion

I have a function which I believe can be simplified into LINQ but have been unable to do so yet.
The function looks like this:
private IList<Colour> GetDifference(IList<Colour> firstList, IList<Colour> secondList)
{
// Create a new list
var list = new List<Colour>();
// Loop through the first list
foreach (var first in firstList)
{
// Create a boolean and set to false
var found = false;
// Loop through the second list
foreach (var second in secondList)
{
// If the first item id is the same as the second item id
if (first.Id == second.Id)
{
// Mark it has being found
found = true;
}
}
// After we have looped through the second list, if we haven't found a match
if (!found)
{
// Add the item to our list
list.Add(first);
}
}
// Return our differences
return list;
}
Can this be converted to a LINQ expression easily?
What is Colour? If it overrides Equals to compare by Id then this would work:
firstList.Except(secondList);
If Colour does not override Equals or it would be wrong for you to do so in the wider context, you could implement an IEqualityComparer<Colour> and pass this as a parameter:
firstList.Except(secondList, comparer);
See the documentation
As noted in the comments below, Except has the added side effect of removing any duplicates in the source (firstList in this example). This may or may not be an issue to you, but should be considered.
If keeping any duplicates in firstList is of importance, then this is the alternative:
var secondSet = new HashSet<Colour>(secondList, comparer);
var result = firstList.Where(c => !secondSet.Contains(c));
As before, comparer is optional if Colour implements appropriate equality
try the following:
var result = firstList.Where(x => !secondList.Any(y => y.ID == x.ID));
Edit:
If you care about runtime and don't mind creating your own IEqualityComparer<>, i would suggest you use Except like Charles suggested in his answer. Except seems to use a hashtable for the second list which speeds it up quite a bit compared to my O(n*m) query. However be aware that Except removes duplicates from secondList as well.

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.

How to check for object of particular type in a HashSet in windows 8?

I have a HashSet of generic type UserControl, which can have various UserControl (login, settings). I want to check whether the set contains object of any particular type (say login). If so i want to get that element.
I know its quite easy to do with a loop, but is there any better way?
Unfortunately, you cannot do it without a loop, because you need to try all elements of your collection to check their types. In fact, it does not matter that you have a hash set: it would work the same with a list, or any other enumerable. However, LINQ lets you hide the loop, like this:
var item = hashSet.OfType<DesiredType>().FirstOrDefault();
As #dasblinkenlight says you can use OfType<T>() LINQ method to hide the loop. His answer also uses FirstOrDefault() method so "contains element?" questions is rephrased to "is not null". Another way is to use Count() > 0 after OfType<T>().
var items = hashSet.OfType<DesiredType>();
if (items.Count() > 0) {
DesiredType item = items.First();
...
}
Third way is to put predicate in the FirstOrDefault() method.
var item = hashSet.FirstOrDefault(x =>
x.getType() == typeof(DesiredType)
);
if (item != null) {
...
}
If your set doesn't change that often, you can use GroupBy(func) to reduce computation complexity to O(1). Idea is to build dictionary once and query it instead.
var groups = new Dictionary<Type, IEnumerable<UserControl>>();
foreach(var group in hashSet.GroupBy(x => x.GetType()))
groups.Add(group.Key, group);
.
.
.
if (groups.ContainsKey(typeof(DesiredType)) {
DesiredType item = items.First();
...
}

How to access a particular data in LINQ query result?

I know, this is very simple for you guys.
Please consider the following code:
string[] str = { "dataReader", "dataTable", "gridView", "textBox", "bool" };
var s = from n in str
where n.StartsWith("data")
select n;
foreach (var x in s)
{
Console.WriteLine(x.ToString());
}
Console.ReadLine();
Supposedly, it will print:
dataReader
dataTable
right?
What if for example I don't know the data, and what the results of the query will be (but I'm sure it will return some results) and I just want to print the second item that will be produced by the query, what should my code be instead of using foreach?
Is there something like array-indexing here?
You're looking forEnumerable.ElementAt.
var secondMatch = str.Where(item => item.StartsWith("data")) //consider null-test
.ElementAt(1);
Console.WriteLine(secondMatch); //ToString() is redundant
SinceWherestreams its results, this will be efficient - enumeration of the source sequence will be discontinued after the second match (the one you're interested in) has been found.
If you find that the implicit guarantee you have that the source will contain two matches is not valid, you can use ElementAtOrDefault.
var secondMatch = str.Where(item => item.StartsWith("data"))
.ElementAtOrDefault(1);
if(secondMatch == null) // because default(string) == null
{
// There are no matches or just a single match..
}
else
{
// Second match found..
}
You could use array-indexing here as you say, but only after you load the results into... an array. This will of course mean that the entire source sequence has to be enumerated and the matches loaded into the array, so it's a bit of a waste if you are only interested in the second match.
var secondMatch = str.Where(item => item.StartsWith("data"))
.ToArray()[1]; //ElementAt will will work too
you got a few options:
s.Skip(1).First();
s.ElementAt(1);
The first is more suited for scenarios where you want X elements but after the y first elements. The second is more clear when you just need a single element on a specific location

Categories

Resources