C# řazení pole struktur přes interface – .NET – Fórum – Programujte.com
 x   TIP: Přetáhni ikonu na hlavní panel pro připnutí webu

C#  řazení pole struktur přes interface – .NET – Fórum – Programujte.comC# řazení pole struktur přes interface – .NET – Fórum – Programujte.com

 

Kartmen
~ Anonymní uživatel
57 příspěvků
22. 12. 2018   #1
-
0
-

Ahoj, mam dotaz jestli je možné hledat v poli struktur pomocí implementace interface jako je např. IEquatable jen přes datový typ proměnné, která je ve struktuře? Nebo je možné hledat přes stejnou strukturu? Snad to chci půjde lépe poznat z kódu. 

    public struct Money : IEquatable<Money>
    {
      public string Value { get; private set; }
      public int ID { get; private set; }

      public Money(string value,int ID) : this()
      {
        Value = value;
      }

      public bool Equals(Money other)
      {
        bool result = this.Value.Equals(other.Value);
        return result;
      }

      public bool Equals(string other)
      {
        bool result = this.Value.Equals(other);
        return result;
      }

      public override bool Equals(Object obj)
      {
        if (obj is Money)
          return Equals((Money)obj);
        else
          return false;
      }
    }

A použití 

        var amounts = new List<Money> { new Money("aaa", 10), new Money("bbb", 11), new Money("ccc", 22) };
        string xxx = "aaa";
        Money ttt = new Money();
        ttt.Value = "bbb";

        int index1 = amounts.IndexOf(ttt);
        int index2 = amounts.IndexOf(xxx);

První vyhledání (index1 ) přes strukturu funguje, ale druhé (index2) jen za pomocí parametru string ne...

Nahlásit jako SPAM
IP: 82.145.223.–
BDS+3
Věrný člen
22. 12. 2018   #2
-
0
-

#1 Kartmen  

    class Program
    {
        static void Main(string[] args)
        {
            var amounts = new List<Money> { new Money("aaa", 10), new Money("bbb", 11), new Money("ccc", 22)};
            string xxx = "aaa";
            Money ttt = new Money("bbb", 4);

            int index1 = amounts.FindIndex(m => m.Equals(ttt));
            int index2 = amounts.FindIndex(m => m.Equals(xxx));

            Console.WriteLine(index1);
            Console.WriteLine(index2);
            Console.ReadKey();
        }
    }

    public struct Money
    {
        public string Value { get; private set; }
        public int ID { get; private set; }

        public Money(string value, int id)// : this()
        {
            Value = value;
            ID = id;
        }

        public bool Equals(Money other)
        {
            bool result = this.Value.Equals(other.Value);
            return result;
        }

        public bool Equals(string other)
        {
            bool result = this.Value.Equals(other);
            return result;
        }
    }

a nemohlo ti fungovat ani toto: "ttt.Value = "bbb";"

protože "Value" máš pouze "private set"

Nahlásit jako SPAM
IP: 185.69.68.–
W11 :)
Kartmen
~ Anonymní uživatel
57 příspěvků
22. 12. 2018   #3
-
0
-

#2 BDS
Fungovalo, ono jsem to testoval v metodě uvnitř té struktury.

Obecně je možně napsat pomocí implementace interface jak spolu porovnávat různé struktury, nebo třídy, přes jednu nebo více shodných vlastností, nebo veřejných proměnných? Respektive hledání podle nějakých dat jedné třídy shodu v kolekci jiné třídy. Nebo je lepší na to prostě napsat cyklus?

Nahlásit jako SPAM
IP: 82.145.222.–
BDS+3
Věrný člen
22. 12. 2018   #4
-
0
-

#3 Kartmen
nevím jestli tomu dotazu nerozumím...

tak porovnávat je můžeš pokud budou mít například shodná rozhraní pro porovnání. 

Money : IComparable<Money>, IComparable<string>

pak to můžeš porovnat s Money i string

nebo se to dělá tak, že vytvoříš třídu která mé určité vlastnosti, a u potomků tyto zděděné vlastnosti porovnáváš

Nahlásit jako SPAM
IP: 185.69.68.–
W11 :)
BDS+3
Věrný člen
22. 12. 2018   #5
-
0
-

#3 Kartmen
dá se to udělat i třeba takto: 

    class Program
    {
        static void Main(string[] args)
        {
            var amounts = new List<Money> { new Money("aaa", 10), new Money("bbb", 11), new Money("ccc", 22)};

            int index = amounts.IndexOf("bbb");

            Console.WriteLine(index);
            Console.ReadKey();
        }
    }



    public struct Money
    {
        public string Value { get; private set; }
        public int ID { get; private set; }

        public Money(string value, int id)// : this()
        {
            Value = value;
            ID = id;
        }

        public static implicit operator Money(string value_s)
        {
            return new Money(value_s, 0);
        }
        
        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public bool Equals(Money other)
        {
            return  Value == other.Value;
        }

        public bool Equals(string other)
        {
            return Value == other;
        }

        public override bool Equals(object obj)
        {
            if(obj is Money)return Equals((Money)obj);
            if (obj is string) return Equals((string)obj);
            return false;
        }
    }

ale není to moc pěkné!

Nahlásit jako SPAM
IP: 185.69.68.–
W11 :)
Kartmen
~ Anonymní uživatel
57 příspěvků
23. 12. 2018   #6
-
0
-

#4 BDS
Právě že ani s přidáním toho rozhraní mi to nefunguje. 

public struct Money : IEquatable<Money>, IEquatable<string>

Je potřeba ještě něco někde jinde poladit? Kompilátor stále řve, že nejde převést string na strukturu Money stejně, jako když tam rozhraní IEquatable<string> není.

Nahlásit jako SPAM
IP: 82.145.223.–
Kartmen
~ Anonymní uživatel
57 příspěvků
23. 12. 2018   #7
-
0
-

#5 BDS
Proč to není moc pěkné? Funguje to trochu jinak, aspoň podle toho co se dál děje po zavolání IndexOf. Otázka je proč to vůbec funguje :) Není implementováno rozhraní, ale ten IndexOf stejně ví co zavolat, takže stačí, že jsou tam metody s příslušným jménem a rozhraní není potřeba? Pak dotaz na GetHashCode, který se tu ani nepoužije, to je zvyk to tam dávat, i když se nepoužívá? Nebo je nějaká metoda, která implicitně porovnává přes GetHashCode, zatímco na IndexOf stačil implicit operator a Equals?

Nahlásit jako SPAM
IP: 82.145.223.–
jerry
~ Anonymní uživatel
504 příspěvků
23. 12. 2018   #8
-
0
-

#1 Kartmen
proč chceš hledat v poli struktur pomocí interface ??? děláš v C# tak si napiš Generic třídu ne ? interface je jen třída co definuje (skoro) prázdné metody. Nějak to nechápu .. ten tvuj dotaz ...

tady máš něco

https://stackoverflow.com/questions/2734914/whats-the-difference-between-iequatable-and-just-overriding-object-equals

IEquatable má definovat  identitu instancí

https://docs.microsoft.com/cs-cz/dotnet/api/system.iequatable-1?view=netframework-4.7.2

ale ty identifikuješ konkrétní hodnoty ...

nechápu

Nahlásit jako SPAM
IP: 2a00:1028:83be:235a:1453:d78d:43fc:75c8...–
BDS+3
Věrný člen
23. 12. 2018   #9
-
0
-

#7 Kartmen

funguje to protože IndexOf očekává Money, protože jde o List<Money>.

static implicit operator se postará o to, že pak můžeš udělat:

Money m = "aaa"; 
tím se dosáhne stejného výsledku jako kdyby se použilo:
Money m = new Money("aaa", 0);

to znamená že, .IndexOf("aaa"); je vlastně .IndexOf(new Money("aaa", 0));

IndexOf(..) tak nehledá string, ale Money.

Rozhraní IEquatable< > nemá z IndexOf souvislost, protože jej nezajímá. Použije jen Equals(object), který zavolá metodu Equals(Money) (Equals(string) se vůbec nevyužije). IEquatable< > tam budeš muset dát, jen pokud jej bude nějaká metoda, očekávat.

Není to moc pěkné, protože při každém spuštění hledání se vytvoří nová instance Money jako vzor hledání.

Takže použití s FindIndex je vhodnější.

Ten "přepis" GetHashCode() je tam jen pro spokojenost kompilátoru, taky mohl jsem toto varování ignorovat. HashCode jsem nikdy nepoužil, tak nevím jak bych jej vhodněji přepsal.  

Tady je ořezaná verze: 

    class Program
    {
        static void Main(string[] args)
        {
            var amounts = new List<Money> { new Money("aaa", 10), new Money("bbb", 11), new Money("ccc", 22)};

            int index = amounts.IndexOf("bbb");

            Console.WriteLine(index);
            Console.ReadKey();
        }
    }



#pragma warning disable CS0659 // Typ přepisuje Object.Equals(object o), ale nepřepisuje Object.GetHashCode().
    public struct Money
#pragma warning restore CS0659 // Typ přepisuje Object.Equals(object o), ale nepřepisuje Object.GetHashCode().
    {
        public string Value { get; private set; }
        public int ID { get; private set; }

        public Money(string value, int id)
        {
            Value = value;
            ID = id;
        }

        public static implicit operator Money(string value_s)
        {
            return new Money(value_s, 0);
        }

        public override bool Equals(object obj)
        {
            if (obj is Money m)
            {
                return Value == m.Value;
            }
            return false;
        }        
    }

Nebo lépe: 

    class Program
    {
        static void Main(string[] args)
        {
            var amounts = new List<Money> { new Money("aaa", 10), new Money("bbb", 11), new Money("ccc", 22)};

            int index = amounts.FindIndex(m => (m.Value == "bbb"));

            Console.WriteLine(index);
            Console.ReadKey();
        }
    }


    public struct Money
    {
        public string Value { get; private set; }
        public int ID { get; private set; }

        public Money(string value, int id)
        {
            Value = value;
            ID = id;
        }        
    }
Nahlásit jako SPAM
IP: 185.69.68.–
W11 :)
Kartmen
~ Anonymní uživatel
57 příspěvků
26. 12. 2018   #10
-
0
-

Vrtam se v C# tak dva týdny, takže se to teprve učím. Většinu se snažím vygooglovat, ale když si nevím rady, tak otravuji tady. Ohledně toho co se tady teď řeší mi přišlo, že většina řešení spočívala v použití interface, nebo linq dotazu.

Zkusím tedy lépe popsat o co mi jde. Jsou dva různé objekty (např. třídy), které spolu nemusí nijak souviset. 

  class class1

  {
    public string jmeno;
    public int barva;
    public long ID;
    public double rychlost;
    public string[] popis;
    public int[] typ;
    //...
  }

  public class class2
  {
    public string jmeno;
    public uint pocet;
    public double plocha;
    public int barva;
    public double rychlost;
    public string[] popis;
    public long ID;
    public int[] typ;
    //...
  }

Já mam kolekce těchto tříd, jejichž volba typu je na mě (pole, List, nebo tak něco). Takže třeba

List<class1> clsL1;
List<class2> clsL2;

V každém listu je několik tisíc prvků a hledám shodu jedné, nebo více vlastností. Cyklem bych to udělal takto  

      foreach (class1 cls1 in clsL1)
      {
        foreach (class2 cls2 in clsL2)
        {
          if (cls1.jmeno == cls2.jmeno)
          {
            if (cls1.barva == cls2.barva)
            {
              if (cls1.ID == cls2.ID)
              {

              //...

              }
            }
          }
        }
      }

A hledám jak se toto běžně řeší, nejlépe způsob kde se píše co nejméně kódu. V tomto případě by se mi hodilo vrátit ke každému indexu listu clsL1 shodny index v listu clsL2 nebo třeba -1 pokud tam shodný prvek není.

Nahlásit jako SPAM
IP: 82.145.220.–
Kartmen
~ Anonymní uživatel
57 příspěvků
26. 12. 2018   #11
-
0
-

#9 BDS
Díky, ten FindIndex vypadá jako to co hledám.

Nahlásit jako SPAM
IP: 82.145.220.–
BDS+3
Věrný člen
26. 12. 2018   #12
-
0
-

#11 Kartmen
tady máš takovou (hloupou) ukázku dědičnosti s využitím rozhraní IComparable pro Sort Listu:

    class Program
    {
        static void Main(string[] args)
        {
            List<Drevo> materialy = new List<Drevo>();
            materialy.Add(new Kulatina() { pevnost_v_tahu=2, pevnost_v_tlaku=4, nazev="buk", prumer = 25, delka = 100 });
            materialy.Add(new Kulatina() { pevnost_v_tahu = 2, pevnost_v_tlaku = 8, nazev = "habr", prumer = 25, delka = 100 });
            materialy.Add(new Hranol() { pevnost_v_tahu = 1, pevnost_v_tlaku = 4, nazev = "javor", sirka=36, tloustka=12 , delka = 100  });
            materialy.Add(new Hranol() { pevnost_v_tahu = 2, pevnost_v_tlaku = 1, nazev = "smrk", sirka = 36, tloustka = 12, delka = 100 });

            foreach(Drevo m in materialy)
            {
                Console.WriteLine(m);
            }
            
            materialy.Sort();
            Console.WriteLine("\nSorted up\n");
            foreach (Drevo m in materialy)
            {
                Console.WriteLine(m);
            }

            Drevo.sort_dir *= -1; //obrátit směr řazení
            materialy.Sort();
            Console.WriteLine("\nSorted down\n");
            foreach (Drevo m in materialy)
            {
                Console.WriteLine(m);
            }

            Console.ReadKey();
        }
    }
    //------------------------------------------
    class Drevo : IComparable<Drevo>
    {
        public static int sort_dir = 1;
        public float pevnost_v_tlaku;
        public float pevnost_v_tahu;
        public string nazev;

        public int CompareTo(Drevo other)
        {
            int c = pevnost_v_tlaku.CompareTo(other.pevnost_v_tlaku);
            if (c == 0)
            {
                return sort_dir * pevnost_v_tahu.CompareTo(other.pevnost_v_tahu);
            }
            else return sort_dir * c;
        }

        public override string ToString()
        {
            return nazev;
        }
    }
    //------------------------------------------
    class Kulatina : Drevo
    {
        public float delka;
        public float prumer;        
    }
    //------------------------------------------
    class Hranol : Drevo
    {
        public float delka;
        public float sirka;
        public float tloustka;
    }
    //------------------------------------------
Nahlásit jako SPAM
IP: 185.69.68.–
W11 :)
Zjistit počet nových příspěvků

Přidej příspěvek

Toto téma je starší jak čtvrt roku – přidej svůj příspěvek jen tehdy, máš-li k tématu opravdu co říct!

Ano, opravdu chci reagovat → zobrazí formulář pro přidání příspěvku

×Vložení zdrojáku

×Vložení obrázku

Vložit URL obrázku Vybrat obrázek na disku
Vlož URL adresu obrázku:
Klikni a vyber obrázek z počítače:

×Vložení videa

Aktuálně jsou podporována videa ze serverů YouTube, Vimeo a Dailymotion.
×
 
Podporujeme Gravatara.
Zadej URL adresu Avatara (40 x 40 px) nebo emailovou adresu pro použití Gravatara.
Email nikam neukládáme, po získání Gravatara je zahozen.
-
Pravidla pro psaní příspěvků, používej diakritiku. ENTER pro nový odstavec, SHIFT + ENTER pro nový řádek.
Sledovat nové příspěvky (pouze pro přihlášené)
Sleduj vlákno a v případě přidání nového příspěvku o tom budeš vědět mezi prvními.
Reaguješ na příspěvek:

Uživatelé prohlížející si toto vlákno

Uživatelé on-line: 0 registrovaných, 17 hostů

Podobná vlákna

Pole struktur — založil Kuba-$

C Pole Struktur String — založil NotBeginner

Velikost pole struktur — založil Redby

 

Hostujeme u Českého hostingu       ISSN 1801-1586       ⇡ Nahoru Webtea.cz logo © 20032024 Programujte.com
Zasadilo a pěstuje Webtea.cz, šéfredaktor Lukáš Churý