How do I know if I am repeating the last item in a collection?

I want to do something different in the last KeyValuePair Dictionary that I am executing.

 For Each item In collection If ItsTheLastItem DoX() Else DoY() End If Next 

Is it possible?

Re-Edit: I do not use dictionary values, in fact I use KeyValuePair s List. I drew them and did not notice later, dumb.

+4
source share
9 answers

Converting a collection to a list (e.g. LINQ ToList ()) and iterating with a for loop (int i = 0) ...

+2
source

If you do not want to implement foreach yourself, use a counter (C # code):

 int count = collection.Count; int counter = 0; foreach(var item in collection) { counter++; if(counter == count) DoX(); else DoY(); } 

Please note that this will only work with streaming IEnumerable<T> , also, depending on the implementation, Count will cause the collection to go through twice.

+8
source

I would make my own extension method. This implementation ensures that you will only walk through the collection once.

 static class IEnumerableExtensions { public static void ForEachExceptTheLast<T>( this IEnumerable<T> source, Action<T> usualAction, Action<T> lastAction ) { var e = source.GetEnumerator(); T penultimate; T last; if (e.MoveNext()) { last = e.Current; while(e.MoveNext()) { penultimate = last; last = e.Current; usualAction(penultimate); } lastAction(last); } } } 

Using:

 Enumerable.Range(1, 5) .ForEachExceptTheLast( x => Console.WriteLine("Not last: " + x), x => Console.WriteLine("Last: " + x) ); 

Output:

 Not last: 1 Not last: 2 Not last: 3 Not last: 4 Last: 5 
+8
source

Why not use:

 List<string> list = new List<string>(); // add items foreach (string text in list) { if (text.Equals(list[list.Count - 1])) { // last item } else { // not last item } } 
+7
source

You cannot do this naturally with IEnumerable<T> , since you won’t know if there are more elements until you try to move on to the next.

However, in my MiscUtil library , I have something called SmartEnumerable that reads one element in advance to provide the following properties:

  • IsFirst
  • IsLast
  • Index
  • Value

See this page for instructions on use. For instance:

 For Each item In collection.ToSmartEnumerable() If item.IsFirst DoX() Else DoY() End If Next 

You will need to use item.Value to get the value of the current item.

One point about iterating over dictionaries - they are actually not in any order. Therefore, while you can iterate, and there will be a first record and a last record, you should not assume that they will be the first record added and the last record respectively. This may not be a problem for your use case, but you should be aware of this.

+2
source

I just had an idea that doesn't use a counter.

 For Each item In collection.GetRange(0, collection.Count - 1) DoY(item) Next DoX(collection.Last) 

Edit: sorry this is for a list, I converted it before, and intellisense gave me List methods instead of Dictionary methods.

+2
source
  foreach (var item in collection.Reverse().Skip(1)) { } // do here the stuff related to list.LastOrDefaut() 

Another approach is to maintain the iteration index and when you press collection.Length-2 or collection.Count()-2 , then stop the loop and do whatever you want with the last element.

But, as @BrokenGlass said, be careful of the side effects your application may have.

In general, you should use Linq with extreme care. For example, every time you iterate over LINQ to an SQL collection, execute the query again, so it is much better to run it sometime willingly, simply by calling .ToList() and use it in the memory collection as much as you want.

+1
source

I created a solution to build an IP string of 4 octets based on @CamiloMartin answer above.

  String sIP; StringBuilder sb = new StringBuilder(); List<String> lstOctets= new List<string>{ usrIP1.Text, usrIP2.Text, usrIP3.Text, usrIP4.Text }; foreach (String Octet in lstOctets.GetRange(0,lstOctets.Count - 1)) { sb.Append(string.Format("{0:d}.", Octet)); } if (lstOctets.Count == 4) sb.Append(string.Format("{0:d}", lstOctets[lstOctets.Count - 1])); else sb.Append(string.Format("{0:d}.0", lstOctets[lstOctets.Count - 1])); sIP = sb.ToString(); 
+1
source

With the help of the dictionary you have several options

 Dim dictionary as new Dictionary(of String, MyObject) For Each item in dictionary // item is KeyValue pair Next For Each item in dictionary.Keys // item is String Next For Each item in dictionary.Keys // item is MyObject Next 

I suggest you iterate over the ValueCollection value and use a counter or compare Equals between the current and last element (which is likely to be slower, but you will keep the counter variable;) Remember to add an empty list check.

 For Each item in dictionary.Values If dictionary.Count > 0 AndAlso _ item.Equals(dictionary.Values(dictionary.Count - 1)) Then Console.WriteLine("Last Item") Else Console.WriteLine("Some other Item") End If Next 
0
source

Source: https://habr.com/ru/post/1333413/


All Articles