procházení kolekce foreach   zodpovězená otázka

C#

Jak mám poznat při procházení kolekce v cyklu foreach, že jsem u poslední položky?

Příklad:

foreach (PriceListItemsRow priceListRow in priceListItems)

{

If (JsemNaKonci(priceListRow))

....

Else

....

}

Potřebuji vymyslet čím nahradit výraz "JsemNaKonci", priceListItems je typový tabulka zděděná z System.Data.DataTable

Jasně je to obejít tak, že o zjistím celkový počet prvků, a v cyklu si budu počítat aktuální pozici.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Poslední řádek by šel poznat například:

DataRow _row = priceListItems.Rows[priceListItems.Rows.Count -1]

další možnost by byla převést DataTable na Enumeration a pak použít metodu Last()

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Jo souhlas pokud musím použít foreach tak bych si řádky v DataTable přetypoval na IEnumerable nebo jako v příkladu na List<...> a pak to prošel.

př:

            //Prohledávaná tabulka
            var dt = new DataTable();
            dt.Columns.Add("Name", typeof (string));
            dt.Rows.Add(dt.NewRow()[0] = "Test1");
            dt.Rows.Add(dt.NewRow()[0] = "Test2");
            dt.Rows.Add(dt.NewRow()[0] = "Test3");

            //přetypování řádků
            var rows = dt.Rows.Cast<DataRow>().ToList();

            foreach (var r in rows)
            {
                if (r == rows.Last())
                {
                    //poslední   
                    Debug.Print("Last");
                    continue;
                }

                Debug.Print("NonLast");

            }
nahlásit spamnahlásit spam 0 odpovědětodpovědět

...přetypoval na IEnumerable nebo jako v příkladu na List<...> a pak to prošel.

Na to pozor. Pro malé příklady je to jedno, ale pokud je ta tabulka opravdu velká, rozhodně není jedno, jestli to přetypujete na IEnumerable nebo na List. Pokud to bude pouze IEnumerable, pak se při každém volání

if (r == rows.Last())

znova projde celá kolekce řádků, což Vám v podstatě z lineárního algoritmu udělá kvadratický. To nechcete. Můžete to nechat jako IEnumerable, ale pak si mimo smyčku deklarujte pomocnou proměnnou a do ní uložte poslední prvek pouze jednou a ze smyšky se pak odkazujte na tuto pomocnou proměnnou.

Ale pro tento problém se mi zdá, že hledáte zbytečně složité řešení. foreach není kladivo na každý hřebík a pokud potřebujete pracovat s indexy, obyčejný for je ideální. Navíc vytvořením Listu z tabulky zbytečně duplikujete data v paměti. Proč? Jen kvůli tomu, abyste je jednou projel? To nemá smysl.

nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
var rowsCount = (dt.Rows.Count - 1);

for (int i = 0; i <= rowsCount; i++)
{
     if (i == rowsCount)
     {
        // posledni radek            
     }
     else
     {
        // .....
     }
}
nahlásit spamnahlásit spam 0 odpovědětodpovědět

Ahoj, stačí jedna pomocná proměnná:

List<Clovek> lidi = new List<Clovek>();
            lidi.Add(new Clovek("Jan"));
            lidi.Add(new Clovek("Karel"));
            lidi.Add(new Clovek("Květoslav"));
            lidi.Add(new Clovek("Jaroslav"));
            lidi.Add(new Clovek("Marek"));


            int pocitadlo = 1;
            foreach(Clovek clovek in lidi)
            {
                //TVUJ KOD

                if(pocitadlo++ == lidi.Count)
                {
                    Console.WriteLine("Posledni clovek je:" +  clovek.Jmeno);
                }
            }
nahlásit spamnahlásit spam 0 odpovědětodpovědět

No pokud vím, tak indexování je vždy on 0, takže Váš kod by padl na OutOfBound Exception nebo jak se přesně jmenuje v .Net

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Nepadlo. On to počítadlo nepoužívá jako indexer. Nepřistupuje přes něj do žádné datové struktury, kde by mohl zkusit číst ze špatné adresy. Používá to jen pro porovnání s počtem.

nahlásit spamnahlásit spam 0 odpovědětodpovědět

Pokud se jedná o IList<T>, kde znáte počet a lze ho efektivně indexovat, použijte jednoduše výraz:

if (item == Items[Items.Count - 1])

Pokud se jedná o obecné IEnumerable<T>, kde počet neznáte a navíc potřebujete, aby byl enumerátor procházen pouze 1x, můžete použít kód jako například:

public class LastEnumerableItem<T>
{
    public T Value { get; set; }
    public bool IsFirst { get; set; }
    public bool IsLast { get; set; }
}

public static class LastEnumerator
{
    public static IEnumerable<LastEnumerableItem<T>> GetLastEnumerable<T>(this IEnumerable<T> source)
    {
        bool isFirst = true;
        using (var enumerator = source.GetEnumerator())
        {
            if (enumerator.MoveNext())
            {
                bool isLast;
                do
                {
                    var current = enumerator.Current;
                    isLast = !enumerator.MoveNext();

                    yield return new LastEnumerableItem<T>
                    {
                        Value = current,
                        IsFirst = isFirst,
                        IsLast = isLast
                    };

                    isFirst = false;
                } while (!isLast);
            }
        }
    }
}

použití pomocné extension metody GetLastEnumerable pak bude:

foreach (var item in items.GetLastEnumerable())
{
    if (item.IsLast)
    {
        //TODO: Use item.Value
    }
}
nahlásit spamnahlásit spam 1 / 1 odpovědětodpovědět
                       
Nadpis:
Antispam: Komu se občas házejí perly?
Příspěvek bude publikován pod identitou   anonym.
  • Administrátoři si vyhrazují právo komentáře upravovat či mazat bez udání důvodu.
    Mazány budou zejména komentáře obsahující vulgarity nebo porušující pravidla publikování.
  • Pokud nejste zaregistrováni, Vaše IP adresa bude zveřejněna. Pokud s tímto nesouhlasíte, příspěvek neodesílejte.

přihlásit pomocí externího účtu

přihlásit pomocí jména a hesla

Uživatel:
Heslo:

zapomenuté heslo

 

založit nový uživatelský účet

zaregistrujte se

 
zavřít

Nahlásit spam

Opravdu chcete tento příspěvek nahlásit pro porušování pravidel fóra?

Nahlásit Zrušit

Chyba

zavřít

feedback