none
Nicht vorhandenes Element in Tupelliste finden RRS feed

  • Frage

  • Hallo Leute. Ich habe zwei Tupellisten

            private List<Tuple<Piece, Byte>> actualFigures = new List<Tuple<Piece, byte>>();
            private List<Tuple<Piece, Byte>> actualFiguresCopy = new List<Tuple<Piece, byte>>();

    Wie finde ich das nicht vorhandene Element von Liste1, verglichen mit Liste2(gerne auch mittels LINQ). Liste1 hat genau 1 Element weniger wie Liste 2. Diese Element(Piece) möchte ich haben. Mit PHP würde ich das mit der Funktion array_diff_assoc() machen. Die gibt es jedoch nicht in C#. Weiß jemand Rat? Bisher versuche ich es so. Das haut aber nicht hin

                    for (int i = 0; i < actualFigures.Count; i++) {
                        //steige aus, sofern unten ein Element gefunden wurde
                        if (haveLeftLoop) break;
                        for (int j = 0; j < actualFiguresCopy.Count; j++) {
                            if (i == j) {
                                //prüfe, ob die Figuren identisch sind..
                                sameFigure = actualFigures[i].Item1.Equals(actualFiguresCopy[j].Item1);
                                //..falls nein,verfrachte die gefundene Figur in die Liste der geschlagenen Figuren
                                if (!sameFigure) {
                                    figuresBeaten.Add(actualFiguresCopy[i].Item1);
                                    haveLeftLoop = true;
                                    break;
                                }
                            }
                        }
                    }






    • Bearbeitet tklustig Freitag, 26. Juli 2019 18:19
    Freitag, 26. Juli 2019 18:10

Antworten

  • Das LINQ statement 

    var result = actualFiguresCopy.Where(x => !actualFigures.Contains(x)).FirstOrDefault();
    funktionert wider Erwarten nicht. Obgleich beide Listen identisch sind, liefert result einen Treffer. Unabhängig davon ist der Treffer nie korrekt, liefert also die falsche Figur

    Habe das jetzt so gelöst:

                    for (int i = 0; i < actualFigures.Count; i++) {
                        //steige aus, sofern unten ein Element gefunden wurde
                        if (haveLeftLoop) break;
                        for (int j = 0; j < actualFiguresCopy.Count; j++) {
                            if (i == j) {
                                //prüfe, ob die Figuren identisch sind..
                                sameFigure = actualFigures[i].Item1.Equals(actualFiguresCopy[j].Item1);
                                //..falls nein,verfrachte die gefundene Figur in die Liste der geschlagenen Figuren
                                if (!sameFigure) {
                                    coordinate = this.giveBackCoordinates(figureMovedX, figureMovedY);
                                    foreach (var item in actualFiguresCopy) {
                                        if (item.Item2 == coordinate) {
                                            figuresBeaten.Add(item.Item1);
                                            break;
                                        }
                                    }
                                    haveLeftLoop = true;
                                    break;
                                }
                            }
                        }
                    }

    Hier noch meine Klasse Piece

    namespace ChessGUI {
    
        #region Enumeration - Figur
        public enum PieceType {
            Bauer,
            Springer,
            Laeufer,
            Turm,
            Dame,
            Koenig
        }
        #endregion
    
        #region Enumeration - Farbe
    
        public enum PieceColor {
            Black,
            White,
            Dummy
        }
        #endregion
    
    
        public class Piece : IPiece {
    
            #region globale Variablen
            private readonly PieceColor _color;
            private readonly PieceType _type;
            #endregion
    
            #region Standardkonstruktor
    
            public Piece() { }
            #endregion
    
            #region Konstruktor - mit Argumenten
            public Piece(PieceType type, PieceColor color) {
                _type = type;
                _color = color;
            }
            #endregion
    
            #region Getter(ohne Setter)
    
            public PieceType Type {
                get { return _type; }
            }
    
            public PieceColor Color {
                get { return _color; }
            }
            #endregion
    
            #region Überschreibt die Methode aus der Klasse Object
            public override int GetHashCode() {
                unchecked {
                    return ((int)_color * 397) ^ (int)_type;
                }
            }
            #endregion
    
            #region Überschreibt die Methode aus der Klasse Object
    
            public override bool Equals(object obj) {
                if (ReferenceEquals(null, obj)) return false;
                if (ReferenceEquals(this, obj)) return true;
                if (obj.GetType() != GetType()) return false;
                return this.Equals((Piece)obj);
            }
            #endregion
    
            #region wird von obiger Methode benötigt
            public bool Equals(Piece figure) {
                return _color == figure._color && _type == figure._type;
            }
            #endregion
        }
    }





    Samstag, 27. Juli 2019 12:03

Alle Antworten

  • Hallo,

    hast Du in deiner Klasse Piece die Vergleichsoperatoren implementiert? Ohne diese kannst Du Klassen nicht miteinander vergleichen.

    Hier ein einfaches Beispiel ohne Operatoren

    class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
    
                Pixel a = new Pixel() { B = 0, G = 0, R = 0 };
                Pixel b = new Pixel() { B = 0, G = 0, R = 0 };
    
                if (a == b || a.Equals(b))
                {
                    //Wert ist immer false
                }
            }
        }
    
        public class Pixel
        {
            public byte R { get; set; }
            public byte G { get; set; }
            public byte B { get; set; }
        }

    Und hier mit Operatoren

    class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("Hello World!");
    
                Pixel a = new Pixel() { B = 0, G = 0, R = 0 };
                Pixel b = new Pixel() { B = 0, G = 0, R = 0 };
    
                if (a == b || a.Equals(b))
                {
                    //Erst jetzt ist ein Vergleich möglich
                }
            }
        }
    
        public class Pixel
        {
            public byte R { get; set; }
            public byte G { get; set; }
            public byte B { get; set; }
    
            public override bool Equals(object obj)
            {
                if (obj is Pixel p)
                {
                    return this == p;
                }
                return false;
            }
    
            public override int GetHashCode()
            {
                return R.GetHashCode() * 5 + G.GetHashCode() * 13 + B.GetHashCode() * 19;
            }
    
            public static bool operator ==(Pixel a, Pixel b)
            {
                return a.B == b.B && a.G == b.G && a.R == b.R;
            }
    
            public static bool operator !=(Pixel a, Pixel b)
            {
                return a.R != b.R || a.G != b.G || a.B != b.B;
            }
        }


    Gruß Thomas
    13 Millionen Schweine landen jährlich im Müll
    Dev Apps von mir: UWP Segoe MDL2 Assets, UI Strings


    Freitag, 26. Juli 2019 22:19
  • Hallo,

    hier noch ergänzend mit Linq.

    Da ich deine Klasse "Piece" nicht kenne, habe ich hier mal eine Beispielklasse erfunden:

    Die erfundene Klasse "Piece":

    public class Piece {
      public int Figur { get; set; }
      public Point Position { get; set; }
      public override string ToString() => $"Figur: {Figur},   ;
    }

    Im ersten Teil des Beispiels verwende ich statt "Tuple" eine erweiterte Klasse, auch wenn das jetzt nicht Teil der Frage war:

    public class PieceExt : Piece {
      public byte AnyByte { get; set; }
      public override string ToString() =>
        $"AnyByte: {AnyByte}, Base: {base.ToString()}";
    }

    So, hier in der folgenden Methode werden einmal Listen mit "PieceExt" erstellt und per Linq ausgewertet. Darunter dann aber mit List<Tuple...>

    public static void Go() {
      // Mit erfundener Klasse...
      // Liste 1
      var pe1 = new List<PieceExt>() {
        new PieceExt() { AnyByte= 1, Figur = 1, Position = new Point(1,1) },
        new PieceExt() { AnyByte= 2, Figur = 2, Position = new Point(2,2) },
        new PieceExt() { AnyByte= 3, Figur = 3, Position = new Point(3,3) }};
      // Liste 2
      var pe2 = new List<PieceExt>(pe1);
        pe2.Add(new PieceExt() { AnyByte = 4, Figur = 4, Position = new Point(4, 4) });
      // Linq-Abfrage
      var result = pe2.Where(x => !pe1.Contains(x)).FirstOrDefault();
      Console.WriteLine(result.ToString());
      Console.ReadKey();
    
      // Mit Tuple-Gedöns
      var actualFigures = new List<Tuple<Piece, byte>>() {
        Tuple.Create(new Piece() { Figur = 1, Position = new Point(1,1) }, (byte)1),
        Tuple.Create(new Piece() { Figur = 2, Position = new Point(2,2) }, (byte)2),
        Tuple.Create(new Piece() { Figur = 3, Position = new Point(3,3) }, (byte)3)};
    
      var actualFiguresCopy = new List<Tuple<Piece, byte>>(actualFigures);
        actualFiguresCopy.Add(Tuple.Create(new Piece() { Figur = 4, Position = new Point(4,4) }, (byte)4));
    
      var result2 = actualFiguresCopy.Where(x => !actualFigures.Contains(x)).FirstOrDefault();
      Console.WriteLine($"Piece: {result2.Item1.ToString()}, Byte: {result2.Item2} ");
      Console.ReadKey();
    }

    Gruß

    Nachtrag:

    Aus mir unbekanntem Grund wird hier im Codeblock der Klasse Piece in der Methode ToString() "Position..." automatisch beim Speichern/Senden entfernt. Es soll da also stehen:

      public override string ToString() =>
        $"Figur: {Figur}, Position: {Position}" ;






    • Bearbeitet K. Pater Samstag, 27. Juli 2019 11:05
    Samstag, 27. Juli 2019 10:53
  • Das LINQ statement 

    var result = actualFiguresCopy.Where(x => !actualFigures.Contains(x)).FirstOrDefault();
    funktionert wider Erwarten nicht. Obgleich beide Listen identisch sind, liefert result einen Treffer. Unabhängig davon ist der Treffer nie korrekt, liefert also die falsche Figur

    Habe das jetzt so gelöst:

                    for (int i = 0; i < actualFigures.Count; i++) {
                        //steige aus, sofern unten ein Element gefunden wurde
                        if (haveLeftLoop) break;
                        for (int j = 0; j < actualFiguresCopy.Count; j++) {
                            if (i == j) {
                                //prüfe, ob die Figuren identisch sind..
                                sameFigure = actualFigures[i].Item1.Equals(actualFiguresCopy[j].Item1);
                                //..falls nein,verfrachte die gefundene Figur in die Liste der geschlagenen Figuren
                                if (!sameFigure) {
                                    coordinate = this.giveBackCoordinates(figureMovedX, figureMovedY);
                                    foreach (var item in actualFiguresCopy) {
                                        if (item.Item2 == coordinate) {
                                            figuresBeaten.Add(item.Item1);
                                            break;
                                        }
                                    }
                                    haveLeftLoop = true;
                                    break;
                                }
                            }
                        }
                    }

    Hier noch meine Klasse Piece

    namespace ChessGUI {
    
        #region Enumeration - Figur
        public enum PieceType {
            Bauer,
            Springer,
            Laeufer,
            Turm,
            Dame,
            Koenig
        }
        #endregion
    
        #region Enumeration - Farbe
    
        public enum PieceColor {
            Black,
            White,
            Dummy
        }
        #endregion
    
    
        public class Piece : IPiece {
    
            #region globale Variablen
            private readonly PieceColor _color;
            private readonly PieceType _type;
            #endregion
    
            #region Standardkonstruktor
    
            public Piece() { }
            #endregion
    
            #region Konstruktor - mit Argumenten
            public Piece(PieceType type, PieceColor color) {
                _type = type;
                _color = color;
            }
            #endregion
    
            #region Getter(ohne Setter)
    
            public PieceType Type {
                get { return _type; }
            }
    
            public PieceColor Color {
                get { return _color; }
            }
            #endregion
    
            #region Überschreibt die Methode aus der Klasse Object
            public override int GetHashCode() {
                unchecked {
                    return ((int)_color * 397) ^ (int)_type;
                }
            }
            #endregion
    
            #region Überschreibt die Methode aus der Klasse Object
    
            public override bool Equals(object obj) {
                if (ReferenceEquals(null, obj)) return false;
                if (ReferenceEquals(this, obj)) return true;
                if (obj.GetType() != GetType()) return false;
                return this.Equals((Piece)obj);
            }
            #endregion
    
            #region wird von obiger Methode benötigt
            public bool Equals(Piece figure) {
                return _color == figure._color && _type == figure._type;
            }
            #endregion
        }
    }





    Samstag, 27. Juli 2019 12:03
  • Das LINQ statement 

    var result = actualFiguresCopy.Where(x => !actualFigures.Contains(x)).FirstOrDefault();
    funktionert wider Erwarten nicht. Obgleich beide Listen identisch sind, liefert result einen Treffer. Unabhängig davon ist der Treffer nie korrekt, liefert also die falsche Figur

    Hi,

    das ist eigenartig. Bei funktioniert das jedenfalls auch mit deiner "Piece"-Klasse.

    Da du aber eine Lösung gefunden hast, brauchen wir das nicht weiter verfolgen.

    Gruß

    Samstag, 27. Juli 2019 12:57