2016-12-20 19 views
1

私はIEqualityComparerインターフェイスについて読んでいます。ここで(もっとして千の言葉を述べている)私のコードLinqとObservableCollectionの2つを比較する<T>を除き

static void Main(string[] args) 
{ 
    var Send = new ObservableCollection<ProdRow>() { 
     new ProdRow() { Code = "8718607000065", Quantity = 1 }, 
     new ProdRow() { Code = "8718607000911", Quantity = 10 } 
    }; 
    var WouldSend = new ObservableCollection<ProdRow>() { 
     new ProdRow() { Code = "8718607000065", Quantity = 1 }, 
     new ProdRow() { Code = "8718607000072", Quantity = 1 }, 
     new ProdRow() { Code = "8718607000256", Quantity = 1 }, 
     new ProdRow() { Code = "8718607000485", Quantity = 1 }, 
     new ProdRow() { Code = "8718607000737", Quantity = 1 }, 
     new ProdRow() { Code = "8718607000911", Quantity = 20 } 
    }; 

    //var sendToMuch = Send.Except(WouldSend).ToList(); 
    //var sendToLittle = WouldSend.Except(Send).ToList(); 

    //if (sendToMuch.Any() || sendToLittle.Any()) 
    // var notGood = true; 
    //else 
    // var okay = true; 

    var sendToMuch = Send.ToList(); 
    var sendToLittle = WouldSend.ToList(); 

    foreach (var s in Send) { 
     var w = WouldSend.FirstOrDefault(d => d.Code.Equals(s.Code)); 

     if (w != null) { 
      if (w.Quantity == s.Quantity) { 
       sendToMuch.Remove(s); 
       sendToLittle.Remove(w); 
       continue; 
      } 
      if (w.Quantity > s.Quantity) { 
       sendToLittle.Single(l => l.Code == w.Code).Quantity = (w.Quantity - s.Quantity); 
       sendToMuch.Remove(s); 
      } else { 
       sendToMuch.Single(l => l.Code == w.Code).Quantity = (s.Quantity - w.Quantity); 
       sendToLittle.Remove(s); 
      } 
     } else { 
      sendToMuch.Add(s); 
     } 
    } 
} 

私はそれが動作することを望んだだろうかコメント行...私がなってしまったものに以下のものがあります。参考として

は、ここで私のProdRowクラスです:

class ProdRow : INotifyPropertyChanged, IEqualityComparer<ProdRow> 
{ 
    private string _code; 
    private int _quantity; 
    public string Code { 
     get { return _code; } 
     set { 
      _code = value; 
      OnPropertyChanged("Code"); 
     } 
    } 
    public int Quantity { 
     get { return _quantity; } 
     set { 
      _quantity = value; 
      OnPropertyChanged("Quantity"); 
     } 
    } 

    private void OnPropertyChanged(string v) { 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(v)); 
    } 

    public new bool Equals(object x, object y) { 
     if (((ProdRow)x).Code.Equals(((ProdRow)y).Code) && ((ProdRow)x).Quantity == ((ProdRow)y).Quantity) 
      return true; 
     else 
      return false; 
    } 
    public int GetHashCode(object obj) { 
     return obj.GetHashCode(); 
    } 
    public bool Equals(ProdRow x, ProdRow y) { 
     if (x.Code.Equals(y.Code) && x.Quantity == y.Quantity) 
      return true; 
     else 
      return false; 
    } 
    public int GetHashCode(ProdRow obj) { 
     throw new NotImplementedException(); 
    } 
    public event PropertyChangedEventHandler PropertyChanged; 
} 

それが数量などのint型を減少させるために知ることができないので、私は、仕事へのコメント部分を期待していなかったけど、もしそこに知っていただきたいと思いますこれを行うためのより効率的な方法です(私が使用した解決方法(コメント行の下))。おそらくstring[]のようなコレクションを平坦化しますか?

P.S. SendWouldSend

+1

をあなたはしたいですか?あなたはこの2つのコレクションを持っていますが、結果は何になりたいですか? – mybirthname

+0

例えば 'sendToLittle'はコード" 8718607000911 "を持つprodrowを持ち、数量10と' sendToMuch'は空でなければなりません。コメントされていないコードの出力である。 –

+0

だから、「量」のDiff(減算)と結合された量のフィルタがゼロではない、 'Code'の(外側の)結合のようなものが必要なのは分かりますか? – grek40

答えて

3

IEqualityComparer<T>の「PascalCase」申し訳ありませんが、そのあなたが比較したいインスタンスクラスを実装する権利インタフェースではありません。 IEqualityComparer<T>の実装は、と比較対象のオブジェクトを作成するためのもので、比較対象のオブジェクトのの外側にあります。これらのオブジェクトのコードにアクセスすることなく2つのオブジェクトが等しくなることを再定義する必要がある場合あなたは文脈に応じて平等のために異なる意味論を使用する必要があります。

厳密に型指定された等価比較のための正しいインターフェイスはIEquatable<T>です。しかし、あなたのケースでは、あなたが必要とするすべてのObjectEquals(object)GetHashCode()をオーバーライドします

public new bool Equals(object obj) { 
    if (obj == this) return true; 
    var other = obj as ProdRow; 
    if (other == null) return false; 
    return Code.Equals(other.Code) && Quantity == other.Quantity; 
} 
public int GetHashCode() { 
    return 31*Code.GetHashCode() + Quantity; 
} 

を限り、計算量が行くように、あなたは負の数とGroupByでそれを行うことができます正確に何

var quantityByCode = WouldSend.Select(p => new {p.Code, p.Quantity}) 
    .Concat(Send.Select(p => new {p.Code, Quantity = -p.Quantity})) 
    .GroupBy(p => p.Code) 
    .ToDictionary(g => g.Key, g => g.Sum(p => p.Quantity)); 
var tooLittle = quantityByCode 
    .Where(p => p.Value > 0) 
    .Select(p => new ProdRow {Code = p.Key, Quantity = p.Value}) 
    .ToList(); 
var tooMuch = quantityByCode 
    .Where(p => p.Value < 0) 
    .Select(p => new ProdRow {Code = p.Key, Quantity = -p.Value}) 
    .ToList(); 
+0

インターフェイスがうまく動作し、最初の製品が完全に見えるようになりました。しかし、第2のものについては、量を減らすべきである。おそらく、あまりにも少なすぎるアイテムを送る2つのコレクションを取得するには、最初にコレクションを平坦化する必要があります。 –

+0

あなたのLinqの追加が本当に好きです!ありがとう!唯一のことは、あまりにも多くの名前をつけていることです。少しだけ切り替える必要があります:) –

+0

@JPHellemons完了。ありがとう! – dasblinkenlight

関連する問題