Diskuze: Viacnásobné mazanie item-ov z colekcie - problém

C# .NET .NET (C# a Visual Basic) Viacnásobné mazanie item-ov z colekcie - problém American English version English version

Avatar
Libor Šimo (libcosenior):

Ahoj,
mám

ObservableCollection<KhmZaznam> KhmZaznamy

a itemy kolekcie ktoré spĺňaju podmienku

item.Mnozstvo == "0"

chcem vymazať.
Vyskúšal som niekoľko variant:

public void VymazNuloveKhm()
{
    foreach (KhmZaznam zaznam in KhmZaznamy)
    {
        if (zaznam.Mnozstvo == "0")
        {
            OdoberKhmZaznam(zaznam);
        }
    }
    // chyba - Collection was modified; enumeration operation may not execute.

    /*int pocet = KhmZaznamy.Count();
    for (int i = 0; i < pocet - 1; i++)
    {
        if (KhmZaznamy[i].Mnozstvo == "0")
        {
            OdoberKhmZaznam(KhmZaznamy[i]);
        }
    }*/
    // Chyba - Index was out of range. Must be non-negative and less than
    // the size of the collection. Parameter name index.

    /*int i = 0;
    do
    {
        if (KhmZaznamy[i].Mnozstvo == "0")
        {
            OdoberKhmZaznam(KhmZaznamy[i]);
        }
        i++;
    } while (KhmZaznamy[i] != null) ;*/
    // Chyba - Index was out of range. Must be non-negative and less than
    // the size of the collection. Parameter name index.
}

a spúšťam to tlačítkom:

private void OdstranPrazdneKhm_Click(object sender, RoutedEventArgs e)
{
    try
    {
        skladnik.VymazNuloveKhm();
        skladnik.Uloz(skladnik.KhmZaznamy, "KhmData.xml");
        skladnik.RefreshKolekcii();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message, "Chyba", MessageBoxButton.OK, MessageBoxImage.Exclamation);
    }
}

Vždy mi to vyhodí chybu. V kóde sú chyby napísané v poznámkach // Chyba -.
Myslím si, že to nejak súvisí s tým, že niektoré itemy kolekcie sú počas cyklu zmazané, ale neviem prísť na to, ako zabezpečiť, aby cyklus prebehol bezchybne.
Poradí niekto?

Odpovědět 3.10.2015 9:45
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Libor Šimo (libcosenior)
Petr Štechmüller:

Ahoj, napadají mě dvě možnosti řešení.

  1. Vytvoř si druhou kolekci typovanou stejně a do ní přidávej ty záznamy, které chceš odstranit. Po projetí celého cyklu můžeš smazat záznamy z hlavní kolekce pomocí té pomocné.
  2. Vytvoř si iterátor, pomocí kterého můžeš jednotlivé záznamy mazat.
Nahoru Odpovědět 3.10.2015 10:00
Pokud spolu kód a komentář nekorespondují, budou patrně oba chybné
Avatar
Odpovídá na Petr Štechmüller
Libor Šimo (libcosenior):

Díky za radu, ale nakoniec to išlo jednoducho:

for (int i = KhmZaznamy.Count - 1; i >= 0; i--)
{
    if (KhmZaznamy[i].Mnozstvo == "0")
    {
        KhmZaznamy.RemoveAt(i);
    }
}
:-)
Nahoru Odpovědět 3.10.2015 10:30
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Petr Nymsa
Redaktor
Avatar
Odpovídá na Libor Šimo (libcosenior)
Petr Nymsa:

V obou cyklech při smazání (nevím jak vypadá metoda OdoberKhmZaznam(KhmZaz­namy[i]); a proč to nemažeš rovnou v cyklu) musíš dekrementovat i. Protože při smazání položky dojde ke zmenšení celkové velikosti

Tj

List<Khm> list = new List<Khm>()
{
    new Khm(1),  new Khm(5),  new Khm(0),  new Khm(3),  new Khm(0)
};

for (int i = 0; i < list.Count; i++)
{
    if (list[i].Mnozstvi == 0)
    {
        list.RemoveAt(i);
        i--;
    }

}

Nebo pokud znáš a vyznáš s v LINQ tak například

list.RemoveAll(x=> x.Mnozstvi == 0);
Nahoru Odpovědět  +2 3.10.2015 10:40
Pokrok nezastavíš, neusni a jdi s ním vpřed
Avatar
Odpovídá na Petr Nymsa
Libor Šimo (libcosenior):

diky, ten moj mi funguje spravne.

Nahoru Odpovědět 3.10.2015 11:49
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Milan Křepelka
Redaktor
Avatar
Odpovídá na Petr Nymsa
Milan Křepelka:

to ještě není linq, ale extension methods

ale jinak jako řešení, velice elegantní

 
Nahoru Odpovědět  +2 3.10.2015 12:17
Avatar
Jan Vargovský
Redaktor
Avatar
Odpovídá na Milan Křepelka
Jan Vargovský:

Ve skutečnosti je to taky LINQ, jen s jinou syntaxí. Kompiluje se to pak stejně na extension metody a ty zase dále na ...

 
Nahoru Odpovědět  ±0 3.10.2015 12:39
Avatar
Odpovídá na Milan Křepelka
Libor Šimo (libcosenior):

Je to elegantne, ale aj tak si myslim, ze to prekladac prelozi rovnako ako ten cyklus. ;-)

Nahoru Odpovědět 3.10.2015 12:41
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Milan Křepelka
Redaktor
Avatar
Odpovídá na Jan Vargovský
Milan Křepelka:

To je stějně hloupé jako říkat raketoplánu raketa.

 
Nahoru Odpovědět 3.10.2015 13:06
Avatar
Odpovídá na Petr Nymsa
Libor Šimo (libcosenior):

Len pre informáciu

list.RemoveAll(x=> x.Mnozstvi == 0);

nefunguje, pretože ObservableCollec­tion nepozná metódu RemoveAll().

Nahoru Odpovědět 3.10.2015 14:13
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 10.