फॉर्च लूप, निर्धारित करें कि लूप का अंतिम चलना कौन सा है


233

मेरे पास एक foreachलूप है और अंतिम आइटम List, जैसे, से चुने जाने पर कुछ तर्क निष्पादित करने की आवश्यकता है :

 foreach (Item result in Model.Results)
 {
      //if current result is the last item in Model.Results
      //then do something in the code
 }

क्या मुझे पता है कि लूप और काउंटरों का उपयोग किए बिना कौन सा लूप अंतिम है?


1
संबंधित प्रश्न के लिए पोस्ट किए गए समाधान के लिए यहां मेरे उत्तर पर एक नज़र डालें ।
ब्रायन गिदोन

जवाबों:


294

यदि आपको अंतिम तत्व के साथ कुछ करने की आवश्यकता है (जैसा कि पिछले तत्व के साथ कुछ अलग करने का विरोध किया जाता है तो LINQ का उपयोग करने से यहां मदद मिलेगी:

Item last = Model.Results.Last();
// do something with last

यदि आपको अंतिम तत्व के साथ कुछ अलग करने की आवश्यकता है तो आपको कुछ इस तरह की आवश्यकता होगी:

Item last = Model.Results.Last();
foreach (Item result in Model.Results)
{
    // do something with each item
    if (result.Equals(last))
    {
        // do something different with the last item
    }
    else
    {
        // do something different with every item but the last
    }
}

हालांकि आपको यह सुनिश्चित करने के लिए एक कस्टम तुलना लिखने की आवश्यकता होगी कि आप यह बता सकते हैं कि आइटम वही था जो आइटम द्वारा लौटाया गया था Last()

इस दृष्टिकोण का उपयोग सावधानी के साथ किया जाना चाहिए क्योंकि Lastसंग्रह के माध्यम से अच्छी तरह से पुनरावृत्ति हो सकती है। हालांकि यह छोटे संग्रह के लिए एक समस्या नहीं हो सकती है, अगर यह बड़ा हो जाता है तो इसका प्रदर्शन प्रभाव पड़ सकता है। यह भी विफल हो जाएगा यदि सूची में डुप्लिकेट आइटम हैं। इस मामले में ऐसा कुछ अधिक उपयुक्त हो सकता है:

int totalCount = result.Count();
for (int count = 0; count < totalCount; count++)
{
    Item result = Model.Results[count];

    // do something with each item
    if ((count + 1) == totalCount)
    {
        // do something different with the last item
    }
    else
    {
        // do something different with every item but the last
    }
}

1
मुझे जो चाहिए था: जब लूप अपने अंतिम आइटम को गर्त में ले जा रहा है: foreach (मॉडल में आइटम परिणाम ।esults) {if (परिणाम == Model.Results.Last ()) {<div> last </ div>; } लगता है कि आप बहुत ज्यादा एक ही बात का मतलब है।
दुर्घटना

10
यदि आप संग्रह छोटा नहीं है, तो आप पूरे संग्रह में दो बार पुनरावृति करेंगे। इस जवाब को देखें ।
शिमी वेइटहैंडलर

54
यदि आप अपने संग्रह में डुप्लिकेट हैं, तो यह वास्तव में काम नहीं करता है। उदाहरण के लिए, यदि आप स्ट्रिंग्स के संग्रह के साथ काम कर रहे हैं, और कोई डुप्लिकेट हैं, तो वह "अंतिम आइटम के साथ अलग" कोड सूची में अंतिम आइटम की प्रत्येक घटना के लिए निष्पादित करेगा।
muttley91

7
यह उत्तर पुराना है, लेकिन इस उत्तर को देखने वाले अन्य लोगों के लिए, आप अंतिम तत्व प्राप्त कर सकते हैं और यह सुनिश्चित कर सकते हैं कि आपको तत्वों का उपयोग करके लूप नहीं करना है: आइटम अंतिम = Model.Results [Model.Results.Count - 1] गिनती किसी सूची की संपत्ति को लूपिंग की आवश्यकता नहीं होती है। यदि आपके पास अपनी सूची में डुप्लिकेट हैं, तो बस लूप के लिए इट्रेटर चर का उपयोग करें। छोरों के लिए नियमित रूप से पुराने खराब नहीं हैं।
माइकल हैरिस

मैं का उपयोग करने का सुझाव देते हैं var last = Model.Result[Model.Result.Count - 1];तेजी से उपयोग करने की तुलना के लिएLast()
Tân

184

कैसे पाश के लिए एक अच्छे पुराने जमाने के बारे में?

for (int i = 0; i < Model.Results.Count; i++) {

     if (i == Model.Results.Count - 1) {
           // this is the last item
     }
}

या Linq और foreach का उपयोग करना:

foreach (Item result in Model.Results)   
{   
     if (Model.Results.IndexOf(result) == Model.Results.Count - 1) {
             // this is the last item
     }
}

14
कई ppl इस तरह एक साधारण समस्या को उखाड़ फेंकते हैं, जब लूप के लिए यह पहले से ही करने में पूरी तरह से सक्षम है। : \
एंड्रयू हॉफमैन

Linq समाधान मेरी पूर्ण पसंदीदा है! साझा करने के लिए धन्यवाद
mecograph

यह स्वीकृत की तुलना में अधिक उपयुक्त उत्तर है।
रतुल

स्ट्रिंग (या मान प्रकार) के संग्रह पर LINQ समाधान का उपयोग करने के इच्छुक किसी को भी नोट करें: यह आम तौर पर काम नहीं करेगा क्योंकि == तुलना विफल हो जाएगी यदि सूची में अंतिम स्ट्रिंग भी सूची में पहले दिखाई देती है। यह केवल तभी काम करेगा जब आप ऐसी सूची के साथ काम कर रहे हों जिसकी कोई डुप्लिकेट स्ट्रिंग न हो।
तवाब वाकिल

दुर्भाग्य से आप इस चालाक समाधान का उपयोग नहीं कर सकते हैं अगर Model.Resultsएक है IEnumerable। आप Count()लूप से पहले कॉल कर सकते हैं लेकिन इससे अनुक्रम का पूरा चलना हो सकता है।
लुका क्रेमोनी

42

Last()कुछ विशेष प्रकारों का उपयोग करने से संपूर्ण संग्रह का लूप समाप्त हो जाएगा!
मतलब कि अगर आप foreachकॉल करते हैं और कॉल करते हैं Last(), तो आपने दो बार लूप किया है! जो मुझे यकीन है कि आप बड़े संग्रह से बचना चाहते हैं।

फिर समाधान एक do whileलूप का उपयोग करना है:

using var enumerator = collection.GetEnumerator();

var last = !enumerator.MoveNext();
T current;

while (!last)
{
  current = enumerator.Current;        

  //process item

  last = !enumerator.MoveNext();        
  if(last)
  {
    //additional processing for last item
  }
}

इसलिए जब तक संग्रह प्रकार प्रकार का नहीं होता है, तब तक सभी संग्रह तत्वों के माध्यम IList<T>से Last()फ़ंक्शन पुनरावृति होगा।

परीक्षा

यदि आपका संग्रह यादृच्छिक पहुँच प्रदान करता है (उदाहरण के लिए लागू होता है IList<T>), तो आप अपने आइटम को निम्नानुसार भी देख सकते हैं।

if(collection is IList<T> list)
  return collection[^1]; //replace with collection.Count -1 in pre-C#8 apps

1
क्या आप सुनिश्चित हैं कि प्रगणक को एक usingवक्तव्य की आवश्यकता है ? मुझे लगता है कि केवल तभी ज़रूरत होती है जब कोई ऑब्जेक्ट ऑपरेटिंग सिस्टम संसाधनों को संभालता है, लेकिन प्रबंधित डेटा संरचनाओं के लिए नहीं।
बिल्ली का बच्चा

IEnumerator IDisposable को कार्यान्वित नहीं करता है, इसलिए संकलन समय त्रुटि को बढ़ाने के साथ उपयोग करने वाली रेखा! समाधान के लिए +1, अधिकांश समय हम केवल फॉर्च्यूनर के बजाय एक के लिए उपयोग नहीं कर सकते, क्योंकि असंख्य संग्रह आइटम रनटाइम पर गणना करते हैं या अनुक्रम यादृच्छिक पहुंच का समर्थन नहीं करते हैं।
सालेह


40

जैसा कि क्रिस शो, लिनक काम करेगा; बस अंतिम का उपयोग करें () एन्युमरेबल में अंतिम एक का संदर्भ पाने के लिए, और जब तक आप उस संदर्भ के साथ काम नहीं कर रहे हैं तब अपना सामान्य कोड करें, लेकिन यदि आप उस संदर्भ के साथ काम कर रहे हैं तो अपनी अतिरिक्त बात करें। इसका नकारात्मक पक्ष यह है कि यह हमेशा O (N) -complexity रहेगा।

इसके बजाय आप काउंट () का उपयोग कर सकते हैं (जो कि O (1) है यदि IEnumerable भी एक ICollection है; यह अधिकांश सामान्य अंतर्निहित IEnumerables के लिए सही है), और एक काउंटर के साथ अपने फ़ॉर्च को हाइब्रिड करें:

var i=0;
var count = Model.Results.Count();
foreach (Item result in Model.Results)
{
    if (++i == count) //this is the last item
}

22
foreach (var item in objList)
{
  if(objList.LastOrDefault().Equals(item))
  {

  }
}

नमस्कार, यह एक सबसे अच्छा तरीका है! सरल और सटीक। एक प्रोग्रामर-बात कर दृष्टिकोण, एक। क्यों नहीं हम चुनते हैं और यह एक +1 अधिक से अधिक देते हैं!
हनी सेतियावान

1
अंतिम आइटम को ब्लॉक से पहले केवल एक बार ( प्रोमो मेमोइज़ेशन ) मिलना चाहिए foreach। इस तरह var lastItem = objList.LastOrDeafault();:। फिर foreachलूप के अंदर से आप इसे इस तरह से देख सकते हैं f (item.Equals(lastItem)) { ... }:। आपके मूल उत्तर objList.LastOrDefault()में प्रत्येक " फॉर्च्यूनर " पर संग्रह से अधिक पुनरावृति होगा ( बहुपद जटिलता शामिल है )।
एलेक्समेल्व

बुरा जवाब। n ^ n के बजाय 2 जटिलता।
शिम्मी वेइटहैंडलर

11

जैसा कि शमी ने बताया है, लास्ट () का उपयोग करना एक प्रदर्शन समस्या हो सकती है, उदाहरण के लिए यदि आपका संग्रह एक LINQ अभिव्यक्ति का लाइव परिणाम है। एकाधिक पुनरावृत्तियों को रोकने के लिए, आप "ForEach" एक्सटेंशन विधि का उपयोग इस तरह कर सकते हैं:

var elements = new[] { "A", "B", "C" };
elements.ForEach((element, info) => {
    if (!info.IsLast) {
        Console.WriteLine(element);
    } else {
        Console.WriteLine("Last one: " + element);
    }
});

विस्तार विधि इस तरह दिखती है (एक अतिरिक्त बोनस के रूप में, यह आपको सूचकांक भी बताएगा और यदि आप पहले तत्व को देख रहे हैं):

public static class EnumerableExtensions {
    public delegate void ElementAction<in T>(T element, ElementInfo info);

    public static void ForEach<T>(this IEnumerable<T> elements, ElementAction<T> action) {
        using (IEnumerator<T> enumerator = elements.GetEnumerator())
        {
            bool isFirst = true;
            bool hasNext = enumerator.MoveNext();
            int index = 0;
            while (hasNext)
            {
                T current = enumerator.Current;
                hasNext = enumerator.MoveNext();
                action(current, new ElementInfo(index, isFirst, !hasNext));
                isFirst = false;
                index++;
            }
        }
    }

    public struct ElementInfo {
        public ElementInfo(int index, bool isFirst, bool isLast)
            : this() {
            Index = index;
            IsFirst = isFirst;
            IsLast = isLast;
        }

        public int Index { get; private set; }
        public bool IsFirst { get; private set; }
        public bool IsLast { get; private set; }
    }
}

9

डैनियल वुल्फ जवाब में सुधार और भी आगे आप IEnumerableकई पुनरावृत्तियों और lambdas से बचने के लिए एक पर ढेर कर सकता है जैसे:

var elements = new[] { "A", "B", "C" };
foreach (var e in elements.Detailed())
{
    if (!e.IsLast) {
        Console.WriteLine(e.Value);
    } else {
        Console.WriteLine("Last one: " + e.Value);
    }
}

विस्तार विधि कार्यान्वयन:

public static class EnumerableExtensions {
    public static IEnumerable<IterationElement<T>> Detailed<T>(this IEnumerable<T> source)
    {
        if (source == null)
            throw new ArgumentNullException(nameof(source));

        using (var enumerator = source.GetEnumerator())
        {
            bool isFirst = true;
            bool hasNext = enumerator.MoveNext();
            int index = 0;
            while (hasNext)
            {
                T current = enumerator.Current;
                hasNext = enumerator.MoveNext();
                yield return new IterationElement<T>(index, current, isFirst, !hasNext);
                isFirst = false;
                index++;
            }
        }
    }

    public struct IterationElement<T>
    {
        public int Index { get; }
        public bool IsFirst { get; }
        public bool IsLast { get; }
        public T Value { get; }

        public IterationElement(int index, T value, bool isFirst, bool isLast)
        {
            Index = index;
            IsFirst = isFirst;
            IsLast = isLast;
            Value = value;
        }
    }
}

1
अन्य उत्तर कई बार स्रोत को पुनरावृत्त नहीं करता है, इसलिए यह वह समस्या नहीं है जिसे आप ठीक कर रहे हैं। आपने वास्तव में उपयोग की अनुमति दी है foreach, जो एक सुधार है।
सर्व जूल

1
@ सरवी मेरा मतलब है कि। मूल उत्तर से एकल पुनरावृत्ति के अलावा मैं लंबोदर से बच रहा हूं।
फैबियो

7

पुनरावृत्ति कार्यान्वयन वह प्रदान नहीं करता है। आपका संग्रह ऐसा हो सकता है जो IListO (1) में अनुक्रमणिका के माध्यम से सुलभ हो । उस स्थिति में आप एक सामान्य- forलूप का उपयोग कर सकते हैं :

for(int i = 0; i < Model.Results.Count; i++)
{
  if(i == Model.Results.Count - 1) doMagic();
}

यदि आप गिनती जानते हैं, लेकिन सूचकांकों के माध्यम से प्रवेश नहीं कर सकते हैं (इस प्रकार, परिणाम एक है ICollection), तो आप अपने आप को एक के शरीर iमें वृद्धि foreachकरके और लंबाई की तुलना करके गिन सकते हैं ।

यह सब पूरी तरह से सुरुचिपूर्ण नहीं है। क्रिस समाधान अब तक मैंने देखा है सबसे अच्छा हो सकता है।


फ़ॉरसी आइडिया क्रिस के समाधान के भीतर अपने काउंटर के प्रदर्शन की तुलना में, मुझे आश्चर्य है कि अधिक खर्च होगा- एक एकल अंतिम () कॉल, या सभी जोड़ा वेतन वृद्धि कार्यों का योग। मुझे संदेह है कि यह करीब होगा।
TTT

6

थोड़ा सरल दृष्टिकोण के बारे में क्या।

Item last = null;
foreach (Item result in Model.Results)
{
    // do something with each item

    last = result;
}

//Here Item 'last' contains the last object that came in the last of foreach loop.
DoSomethingOnLastElement(last);

2
मैं नहीं जानता कि किसी ने आपको वोट क्यों दिया। यह पूरी तरह से स्वीकार्य है कि आप पहले से ही एक प्रदर्शन कर रहे हैं और ओ (एन) की लागत लगा रहे हैं।
अरविमन

2
इस तथ्य के बावजूद कि अंतिम आइटम का पता लगाने के लिए उत्तर सही है, यह ओपी की स्थिति के अनुरूप नहीं है " ..., निर्धारित करें कि लूप का अंतिम चलना कौन है "। इसलिए, आप यह निर्धारित करने में सक्षम नहीं हैं कि अंतिम पुनरावृत्ति वास्तव में अंतिम है, और, इस प्रकार, आप इसे अलग तरीके से संभाल नहीं सकते हैं या इसे अनदेखा भी कर सकते हैं। यही कारण है कि किसी ने आपको नीचा दिखाया है। @arviman आप इसके बारे में बहुत उत्सुक थे।
एलेक्समेल्व

1
आप सही हैं, मैं पूरी तरह से इसे @ एंड्री-डब्ल्यूडी से चूक गया। मुझे लगता है कि ठीक करने का उपाय लूप से पहले एक बार "अंतिम" कॉल करना है (लूप के अंदर ऐसा नहीं कर सकते क्योंकि यह ओ (एन ^ 2) होगा और फिर जांच लें कि क्या संदर्भ इससे मेल खाता है।
अरविमान

5

सबसे अच्छा तरीका शायद लूप के बाद उस कदम को निष्पादित करना होगा: उदा

foreach(Item result in Model.Results)
{
   //loop logic
}

//Post execution logic

या यदि आपको अंतिम परिणाम के लिए कुछ करने की आवश्यकता है

foreach(Item result in Model.Results)
{
   //loop logic
}

Item lastItem = Model.Results[Model.Results.Count - 1];

//Execute logic on lastItem here

3

स्वीकृत उत्तर संग्रह में डुप्लिकेट के लिए काम नहीं करेगा। यदि आप पर सेट हैं foreach, तो आप बस अपना स्वयं का अनुक्रमण चर (ओं) को जोड़ सकते हैं।

int last = Model.Results.Count - 1;
int index = 0;
foreach (Item result in Model.Results)
{
    //Do Things

    if (index == last)
        //Do Things with the last result

    index++;
}

2

Linq और foreach का उपयोग करना:

foreach (Item result in Model.Results)   
{   
     if (Model.Results.IndexOf(result) == Model.Results.Count - 1) {
             // this is the last item
     }
}

https://code.i-harness.com/en/q/7213ce


1
यह तभी काम करेगा जब सूची / संग्रह में विशिष्ट मूल्य हों।
मेललेक

1

".Last ()" मेरे लिए काम नहीं किया, इसलिए मुझे ऐसा कुछ करना पड़ा:

Dictionary<string, string> iterativeDictionary = someOtherDictionary;
var index = 0;
iterativeDictionary.ForEach(kvp => 
    index++ == iterativeDictionary.Count ? 
        /*it's the last item */ :
        /*it's not the last item */
);

1

जॉन स्कीट के उत्कृष्ट कोड के लिए कुछ छोटे समायोजन करना, आप पिछले और अगले आइटम तक पहुंच की अनुमति देकर इसे और भी स्मार्ट बना सकते हैं। बेशक इसका मतलब है कि आपको कार्यान्वयन में 1 आइटम से आगे पढ़ना होगा। प्रदर्शन कारणों से, पिछले और अगले आइटम को केवल वर्तमान पुनरावृत्ति आइटम के लिए ही रखा गया है। यह इस प्रकार चलता है:

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
// Based on source: http://jonskeet.uk/csharp/miscutil/

namespace Generic.Utilities
{
    /// <summary>
    /// Static class to make creation easier. If possible though, use the extension
    /// method in SmartEnumerableExt.
    /// </summary>
    public static class SmartEnumerable
    {
        /// <summary>
        /// Extension method to make life easier.
        /// </summary>
        /// <typeparam name="T">Type of enumerable</typeparam>
        /// <param name="source">Source enumerable</param>
        /// <returns>A new SmartEnumerable of the appropriate type</returns>
        public static SmartEnumerable<T> Create<T>(IEnumerable<T> source)
        {
            return new SmartEnumerable<T>(source);
        }
    }

    /// <summary>
    /// Type chaining an IEnumerable&lt;T&gt; to allow the iterating code
    /// to detect the first and last entries simply.
    /// </summary>
    /// <typeparam name="T">Type to iterate over</typeparam>
    public class SmartEnumerable<T> : IEnumerable<SmartEnumerable<T>.Entry>
    {

        /// <summary>
        /// Enumerable we proxy to
        /// </summary>
        readonly IEnumerable<T> enumerable;

        /// <summary>
        /// Constructor.
        /// </summary>
        /// <param name="enumerable">Collection to enumerate. Must not be null.</param>
        public SmartEnumerable(IEnumerable<T> enumerable)
        {
            if (enumerable == null)
            {
                throw new ArgumentNullException("enumerable");
            }
            this.enumerable = enumerable;
        }

        /// <summary>
        /// Returns an enumeration of Entry objects, each of which knows
        /// whether it is the first/last of the enumeration, as well as the
        /// current value and next/previous values.
        /// </summary>
        public IEnumerator<Entry> GetEnumerator()
        {
            using (IEnumerator<T> enumerator = enumerable.GetEnumerator())
            {
                if (!enumerator.MoveNext())
                {
                    yield break;
                }
                bool isFirst = true;
                bool isLast = false;
                int index = 0;
                Entry previous = null;

                T current = enumerator.Current;
                isLast = !enumerator.MoveNext();
                var entry = new Entry(isFirst, isLast, current, index++, previous);                
                isFirst = false;
                previous = entry;

                while (!isLast)
                {
                    T next = enumerator.Current;
                    isLast = !enumerator.MoveNext();
                    var entry2 = new Entry(isFirst, isLast, next, index++, entry);
                    entry.SetNext(entry2);
                    yield return entry;

                    previous.UnsetLinks();
                    previous = entry;
                    entry = entry2;                    
                }

                yield return entry;
                previous.UnsetLinks();
            }
        }

        /// <summary>
        /// Non-generic form of GetEnumerator.
        /// </summary>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }

        /// <summary>
        /// Represents each entry returned within a collection,
        /// containing the value and whether it is the first and/or
        /// the last entry in the collection's. enumeration
        /// </summary>
        public class Entry
        {
            #region Fields
            private readonly bool isFirst;
            private readonly bool isLast;
            private readonly T value;
            private readonly int index;
            private Entry previous;
            private Entry next = null;
            #endregion

            #region Properties
            /// <summary>
            /// The value of the entry.
            /// </summary>
            public T Value { get { return value; } }

            /// <summary>
            /// Whether or not this entry is first in the collection's enumeration.
            /// </summary>
            public bool IsFirst { get { return isFirst; } }

            /// <summary>
            /// Whether or not this entry is last in the collection's enumeration.
            /// </summary>
            public bool IsLast { get { return isLast; } }

            /// <summary>
            /// The 0-based index of this entry (i.e. how many entries have been returned before this one)
            /// </summary>
            public int Index { get { return index; } }

            /// <summary>
            /// Returns the previous entry.
            /// Only available for the CURRENT entry!
            /// </summary>
            public Entry Previous { get { return previous; } }

            /// <summary>
            /// Returns the next entry for the current iterator.
            /// Only available for the CURRENT entry!
            /// </summary>
            public Entry Next { get { return next; } }
            #endregion

            #region Constructors
            internal Entry(bool isFirst, bool isLast, T value, int index, Entry previous)
            {
                this.isFirst = isFirst;
                this.isLast = isLast;
                this.value = value;
                this.index = index;
                this.previous = previous;
            }
            #endregion

            #region Methods
            /// <summary>
            /// Fix the link to the next item of the IEnumerable
            /// </summary>
            /// <param name="entry"></param>
            internal void SetNext(Entry entry)
            {
                next = entry;
            }

            /// <summary>
            /// Allow previous and next Entry to be garbage collected by setting them to null
            /// </summary>
            internal void UnsetLinks()
            {
                previous = null;
                next = null;
            }

            /// <summary>
            /// Returns "(index)value"
            /// </summary>
            /// <returns></returns>
            public override string ToString()
            {
                return String.Format("({0}){1}", Index, Value);
            }
            #endregion

        }
    }
}

1

foreachअंतिम तत्व पर प्रतिक्रिया करने के लिए कैसे परिवर्तित करें :

List<int> myList = new List<int>() {1, 2, 3, 4, 5};
Console.WriteLine("foreach version");
{
    foreach (var current in myList)
    {
        Console.WriteLine(current);
    }
}
Console.WriteLine("equivalent that reacts to last element");
{
    var enumerator = myList.GetEnumerator();
    if (enumerator.MoveNext() == true) // Corner case: empty list.
    {
        while (true)
        {
            int current = enumerator.Current;

            // Handle current element here.
            Console.WriteLine(current);

            bool ifLastElement = (enumerator.MoveNext() == false);
            if (ifLastElement)
            {
                // Cleanup after last element
                Console.WriteLine("[last element]");
                break;
            }
        }
    }
    enumerator.Dispose();
}

1

बस पिछले मूल्य को स्टोर करें और लूप के अंदर इसके साथ काम करें। फिर अंत में 'पिछला' मान अंतिम आइटम होगा, जिससे आप इसे अलग तरीके से संभाल पाएंगे। कोई गिनती या विशेष पुस्तकालयों की आवश्यकता नहीं है।

bool empty = true;
Item previousItem;

foreach (Item result in Model.Results)
{
    if (!empty)
    {
        // We know this isn't the last item because it came from the previous iteration
        handleRegularItem(previousItem);
    }

    previousItem = result;
    empty = false;
}

if (!empty)
{
    // We know this is the last item because the loop is finished
    handleLastItem(previousItem);
}

1

आप सिर्फ लूप के लिए उपयोग कर सकते हैं और शरीर के ifअंदर अतिरिक्त जोड़ने की आवश्यकता नहीं forहै:

for (int i = 0; i < Model.Results.Count - 1; i++) {
    var item = Model.Results[i];
}

-1में forहालत पिछले आइटम लंघन का ख्याल रखता है।


लूप के लिए -1 अंतिम आइटम को छोड़ देने का ध्यान नहीं रखता है। यदि आपको -1 शामिल नहीं है, तो आपको एक IndexOutOfRangeException मिलेगी।
जा एच

0

जॉन स्कीट ने ए SmartEnumerable<T> ने इस सटीक मुद्दे को हल करने के लिए थोड़ी देर पहले प्रकार । आप देख सकते हैं कि यह यहां लागू है:

http://codeblog.jonskeet.uk/2007/07/27/smart-enumerations/

डाउनलोड करने के लिए: http://www.yoda.arachsys.com/csharp/miscutil/


0

पिछले एक को छोड़कर प्रत्येक तत्व के लिए कुछ अतिरिक्त करने के लिए, फ़ंक्शन आधारित दृष्टिकोण का उपयोग किया जा सकता है।

delegate void DInner ();

....
    Dinner inner=delegate 
    { 
        inner=delegate 
        { 
            // do something additional
        } 
    }
    foreach (DataGridViewRow dgr in product_list.Rows)
    {
        inner()
        //do something
    }
}

इस दृष्टिकोण में स्पष्ट कमियां हैं: अधिक जटिल मामलों के लिए कम कोड स्पष्टता। प्रतिनिधियों को बुलाना बहुत प्रभावी नहीं हो सकता है। समस्या निवारण काफी आसान नहीं हो सकता है। उज्ज्वल पक्ष - कोडिंग मजेदार है!

यह कहने के बाद, मैं तुच्छ मामलों में छोरों के लिए सादे का उपयोग करने का सुझाव दूंगा, यदि आप जानते हैं कि आपके संग्रह की गिनती बहुत धीमी नहीं है।


0

दूसरा तरीका, जिसे मैंने पोस्ट नहीं किया, वह है क्यू का उपयोग करना। यह एक स्किपस्टैस्ट () विधि को लागू करने के लिए आवश्यक से अधिक पुनरावृति के बिना एक तरह से अनुरूप है। यह तरीका आपको किसी भी अंतिम आइटम पर ऐसा करने की अनुमति देगा।

public static void ForEachAndKnowIfLast<T>(
    this IEnumerable<T> source,
    Action<T, bool> a,
    int numLastItems = 1)
{
    int bufferMax = numLastItems + 1;
    var buffer = new Queue<T>(bufferMax);
    foreach (T x in source)
    {
        buffer.Enqueue(x);
        if (buffer.Count < bufferMax)
            continue; //Until the buffer is full, just add to it.
        a(buffer.Dequeue(), false);
    }
    foreach (T item in buffer)
        a(item, true);
}

इसे कॉल करने के लिए आप निम्नलिखित कार्य करेंगे:

Model.Results.ForEachAndKnowIfLast(
    (result, isLast) =>
    {
        //your logic goes here, using isLast to do things differently for last item(s).
    });

0
     List<int> ListInt = new List<int> { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };


                int count = ListInt.Count;
                int index = 1;
                foreach (var item in ListInt)
                {
                    if (index != count)
                    {
                        Console.WriteLine("do something at index number  " + index);
                    }
                    else
                    {
                        Console.WriteLine("Foreach loop, this is the last iteration of the loop " + index);
                    }
                    index++;

                }
 //OR
                int count = ListInt.Count;
                int index = 1;
                foreach (var item in ListInt)
                {
                    if (index < count)
                    {
                        Console.WriteLine("do something at index number  " + index);
                    }
                    else
                    {
                        Console.WriteLine("Foreach loop, this is the last iteration of the loop " + index);
                    }
                    index++;

                }

0

आप इसके लिए विशेष रूप से समर्पित एक विस्तार विधि बना सकते हैं:

public static class EnumerableExtensions {
    public static bool IsLast<T>(this List<T> items, T item)
        {
            if (items.Count == 0)
                return false;
            T last = items[items.Count - 1];
            return item.Equals(last);
        }
    }

और आप इसे इस तरह से उपयोग कर सकते हैं:

foreach (Item result in Model.Results)
{
    if(Model.Results.IsLast(result))
    {
        //do something in the code
    }
}

0

@ शिम्मी की प्रतिक्रिया के आधार पर, मैंने एक विस्तार विधि बनाई जो वह समाधान है जो हर कोई चाहता है। यह सरल, उपयोग में आसान है, और केवल एक बार संग्रह के माध्यम से लूप करता है।

internal static class EnumerableExtensions
{
    public static void ForEachLast<T>(this IEnumerable<T> collection, Action<T>? actionExceptLast = null, Action<T>? actionOnLast = null)
    {
        using var enumerator = collection.GetEnumerator();
        var isNotLast = enumerator.MoveNext();
        while (isNotLast)
        {
            var current = enumerator.Current;
            isNotLast = enumerator.MoveNext();
            var action = isNotLast ? actionExceptLast : actionOnLast;
            action?.Invoke(current);
        }
    }
}

यह किसी भी पर काम करता है IEnumerable<T>। उपयोग इस तरह दिखता है:

var items = new[] {1, 2, 3, 4, 5};
items.ForEachLast(i => Console.WriteLine($"{i},"), i => Console.WriteLine(i));

आउटपुट जैसा दिखता है:

1,
2,
3,
4,
5

इसके अतिरिक्त, आप इसे एक Selectशैली विधि में बना सकते हैं । फिर, उस एक्सटेंशन का पुन: उपयोग करें ForEach। यह कोड इस तरह दिखता है:

internal static class EnumerableExtensions
{
    public static void ForEachLast<T>(this IEnumerable<T> collection, Action<T>? actionExceptLast = null, Action<T>? actionOnLast = null) =>
        // ReSharper disable once IteratorMethodResultIsIgnored
        collection.SelectLast(i => { actionExceptLast?.Invoke(i); return true; }, i => { actionOnLast?.Invoke(i); return true; }).ToArray();

    public static IEnumerable<TResult> SelectLast<T, TResult>(this IEnumerable<T> collection, Func<T, TResult>? selectorExceptLast = null, Func<T, TResult>? selectorOnLast = null)
    {
        using var enumerator = collection.GetEnumerator();
        var isNotLast = enumerator.MoveNext();
        while (isNotLast)
        {
            var current = enumerator.Current;
            isNotLast = enumerator.MoveNext();
            var selector = isNotLast ? selectorExceptLast : selectorOnLast;
            //https://stackoverflow.com/a/32580613/294804
            if (selector != null)
            {
                yield return selector.Invoke(current);
            }
        }
    }
}

-1

हम लूप में अंतिम आइटम की जांच कर सकते हैं।

foreach (Item result in Model.Results)
{
    if (result==Model.Results.Last())
    {
        // do something different with the last item
    }
}

-2
foreach (DataRow drow in ds.Tables[0].Rows)
            {
                cnt_sl1 = "<div class='col-md-6'><div class='Slider-img'>" +
                          "<div class='row'><img src='" + drow["images_path"].ToString() + "' alt='' />" +
                          "</div></div></div>";
                cnt_sl2 = "<div class='col-md-6'><div class='Slider-details'>" +
                          "<p>" + drow["situation_details"].ToString() + "</p>" +
                          "</div></div>";
                if (i == 0)
                {
                    lblSituationName.Text = drow["situation"].ToString();
                }
                if (drow["images_position"].ToString() == "0")
                {
                    content += "<div class='item'>" + cnt_sl1 + cnt_sl2 + "</div>";
                    cnt_sl1 = "";
                    cnt_sl2 = "";
                }
                else if (drow["images_position"].ToString() == "1")
                {
                    content += "<div class='item'>" + cnt_sl2 + cnt_sl1 + "</div>";
                    cnt_sl1 = "";
                    cnt_sl2 = "";
                }
                i++;
            }

(!) आपका कोड कितना भी अच्छा या कितना भी बुरा क्यों न हो। स्पष्टीकरण के बिना आमतौर पर इसका कोई मूल्य नहीं होता है।
एलेक्समेल्व

इसके अलावा यह अधिक इंजीनियर लगता है।
mecograph

-3

आप इस तरह कर सकते हैं:

foreach (DataGridViewRow dgr in product_list.Rows)
{
    if (dgr.Index == dgr.DataGridView.RowCount - 1)
    {
        //do something
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.