2017-10-08 3 views
0

私はXYZの座標を3つのプロパティと共に記述するために使用するクラスを持っています。クラスは1つのプロパティのifと等しいです

クラスは次のようになります。

class dwePoint 
{ 
     public double X { get; set; } 
     public double Y { get; set; } 
     public double Z { get; set; } 
     public string Prop1 { get; set; } 
     public string Prop2 { get; set; } 
     public string Prop3 { get; set; } 

     public override bool Equals(object obj) 
     { 
      return Equals(obj as dwePoint); 
     } 

     protected bool Equals(dwePoint other) 
     { //This doesnt seem to work 
      if(Prop1== "Keep") 
      { 
       return false; 
      } 
      return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z); 
     } 

     public override int GetHashCode() 
     { 
      unchecked 
      { 
       var hashCode = X.GetHashCode(); 
       hashCode = (hashCode * 397)^Y.GetHashCode(); 
       hashCode = (hashCode * 397)^Prop1.GetHashCode(); 
       hashCode = (hashCode * 397)^Z.GetHashCode(); 
       return hashCode; 
      } 
     } 
} 

EqualsXYZを確認し、私はプロパティを無視して、唯一の実際の座標に基づいて、重複を除外することができます。 は私のコードでは、私は、リストを使用するので、私はList.Distinct()

を呼び出す今、私はまだ把握カント一つのことがある: それは2ポイントが同じXYZであることは可能であるが、異なる性質を有します。 その場合、私はいつも特定の文字列(例えば "Keep")でその文字列を保持し、常に他の値を持つものを削除したいと思っています。

私はすでに任意の運なしに、いくつかのif文をしようとしていた...

私はこれをどのように処理しますか?

+1

*すでにif文*を試していました。あなたは見せてくれますか? –

+0

@ S.Akbari編集しました。私の論理は、同じXYZを持つ2ポイント(またはそれ以上)が存在する可能性があり、2のうち1つだけがProp1に「Keep」を持つことができました。したがって、1つは偽であるが、他のものをチェックすることは、それを複製として返すべきである。 –

+0

オブジェクトを 'Prop1 ==" Keep "と比較すると、これは' false'を返します。これは明らかに間違っています。 –

答えて

1

実際にDistinctではEqualsが使用されているため、これは同等である必要があるため入力する必要がありません。オブジェクト間に違いがあることに気付くことさえありません。

新しいクラスを使用してクラスを作成する方がよいと思います。座標と3つのプロパティを含むPoint3Dその後、ポイントごとにグループ化することができ、複数の等価ポイントを持つすべてのものに対して、保持するものとして独自のロジックを適用できます。コードで

class Point3D 
{ 
    public double X { get; set; } 
    public double Y { get; set; } 
    public double Z { get; set; } 
    // Equals and get hash code here 
} 

class dwePoint 
{ 
    Point3D Coordinate {get;} 
    public string Prop1 { get; set; } 
    public string Prop2 { get; set; } 
    public string Prop3 { get; set; } 
} 

// Filter list by applying grouping and your custom logic 
points = points.GroupBy(p => p.Coordinate) 
    .Select(x => 
     x.OrderByDescending(p => p.Prop1 == "Keep") // Sort so the element you want to keep is first 
     .First()         // If there is only one element, the ordering will not matter 
    ).ToList(); 

あなたが本当にしたい場合のみ座標がEqualsに一部がかかるため、GroupByはまた、あなたの現在のクラスの設計で動作します。

+0

あなたのexplenationとコードサンプルに感謝します。それを数回読んで完全に理解する必要がありますが、それは私に多くの助けになります(私は専門的なコーディングの背景がありません) –

+0

私はそれを働かせて、今それをかなり理解しています。 もう1つだけ私は不思議です。私は自分の好みの文字列の順序を指定できますか?最初のピックは "Keep"の2番目の "SomeName"は3番目の "SomethingElse"などとなります。 –

-1

私はdriisが提供しているのと同じ回答を念頭に置いていました。 しかし、私はあなたに別のオプションを提供したいと思います。

あなた自身で拡張メソッドとしてDistinctを記述することができます。 ここには回避策があります。サンプルコードを書いたので、理解しやすくなりました。

が、それはあなたを助けることを願っています

static class Program 
{ 
    static void Main(string[] args) 
    { 
     List<Abc> list = new List<Abc>() 
     { 
      new Abc() 
      { 
       a = 5, 
       b = 6, 
       s = "Phew" 
      }, 
      new Abc() 
      { 
       a = 9, 
       b = 10, 
       s = "Phew" 
      }, 
      new Abc() 
      { 
       a = 5, 
       b = 6, 
       s = "Keep" 
      }, 
      new Abc() 
      { 
       a = 9, 
       b = 10, 
       s = "Keep" 
      }, 
      new Abc() 
      { 
       a = 5, 
       b = 6, 
       s = "Phew" 
      }, 
      new Abc() 
      { 
       a = 9, 
       b = 10, 
       s = "Phew" 
      }, 
     }; 
     list = list.MyDistinct(); 
    } 

    // Extension Method 
    public static List<Abc> MyDistinct(this List<Abc> list) 
    { 
     List<Abc> newList = new List<Abc>(); 
     foreach (Abc item in list) 
     { 
      Abc found = newList.FirstOrDefault(x => x.Equals(item)); 
      if (found == null) 
      { 
       newList.Add(item); 
      } 
      else 
      { 
       if (found.s != "Keep" && item.s == "Keep") 
       { 
        newList.Remove(found); 
        newList.Add(item); 
       } 
      } 
     } 
     return newList; 
    } 
} 

class Abc 
{ 
    public int a, b; 
    public string s; 

    public override bool Equals(object obj) 
    { 
     Abc other = obj as Abc; 
     return a == other.a && b == other.b; 
    } 

    public override int GetHashCode() 
    { 
     return a.GetHashCode()^b.GetHashCode(); 
    } 
} 
...

0

PROP1は== nullの場合、あなたはそれを修正する必要がある場合はあなたのGetHashCodeメソッドはnullrefに実行されます。

もう1つの解決策:AggregateとLamdaを使用してリストを区別します。あなたのクラスのEqual()はX、Y、Zだけを比較します。集約ラムダはあなたが望むものを確実に保持します。おそらく、拡張メソッドまたは関数にAggregateを置いてください。

static void Main() 
{ 
    List<dwePoint> points = new List<dwePoint>(); 
    // Testdata 
    for (int x = 0; x < 3; x++) 
     for (int y = 0; y < 3; y++) 
      for (int z = 0; z < 3; z++) 
      { 
       points.Add(new dwePoint { X = x, Y = y, Z = z }); 
       if (x == y && x == z) // and some duplicates to Keep 
        points.Add(new dwePoint { X = x, Y = y, Z = z, Prop1 = "Keep" }); 
      } 

    // prefer the ones with "Keep" in Prop1 
    var distincts = points.Aggregate(new HashSet<dwePoint>(), (acc, p) => 
    { 
     if (acc.Contains(p)) 
     { 
      var oldP = acc.First(point => point.X == p.X && point.Y == p.Y && point.Z == p.Z); 
      if (oldP.Prop1 == "Keep") 
      { 
       // do nothing - error, second point with "keep" 
      } 
      else 
      { 
       acc.Remove(oldP); 
       acc.Add(p); // to use this ones other props later on .... 
      } 
     } 
     else 
      acc.Add(p); 

     return acc; 
    }).ToList(); 

    Console.WriteLine(string.Join(" - ", points)); 
    Console.WriteLine(string.Join(" - ", distincts)); 
    Console.ReadLine(); 
} 


private class dwePoint 
{ 
    public string Prop1 { get; set; } 
    public string Prop2 { get; set; } 
    public string Prop3 { get; set; } 
    public double X { get; set; } 
    public double Y { get; set; } 
    public double Z { get; set; } 

    public override bool Equals(object obj) 
    { 
     return Equals(obj as dwePoint); 
    } 

    public override int GetHashCode() 
    { 
     unchecked 
     { 
      var hashCode = X.GetHashCode(); 
      hashCode = (hashCode * 397)^Y.GetHashCode(); 
      hashCode = (hashCode * 397)^Z.GetHashCode(); 
      return hashCode; 
     } 
    } 

    public override string ToString() => $"{X}-{Y}-{Z}-{Prop1}-{Prop2}-{Prop3}"; 

    protected bool Equals(dwePoint other) 
    { 
     return X.Equals(other.X) && Y.Equals(other.Y) && Z.Equals(other.Z); 
    } 
} 
関連する問題