2

次のように、オブジェクトと 2 つのリストがあります。

    public class MyObject
    {
        public int Key;
        public DateTime Day;
        public decimal Value;
    }        

    List<MyObject> listA = new List<MyObject>()
    {
        new MyObject() { Key = 1, Day = new DateTime(2012, 12, 17), Value = 8 },
        new MyObject() { Key = 1, Day = new DateTime(2012, 12, 18), Value = 8 },
        new MyObject() { Key = 2, Day = new DateTime(2012, 12, 17), Value = 8 },
        new MyObject() { Key = 3, Day = new DateTime(2012, 12, 17), Value = 4 },
        new MyObject() { Key = 4, Day = new DateTime(2012, 12, 17), Value = 4 }
    };

    List<MyObject> listB = new List<MyObject>()
    {
        new MyObject() { Key = 1, Day = new DateTime(2012, 12, 17), Value = 2 },
        new MyObject() { Key = 1, Day = new DateTime(2012, 12, 18), Value = 8 },
        new MyObject() { Key = 3, Day = new DateTime(2012, 12, 17), Value = 8 },
        new MyObject() { Key = 4, Day = new DateTime(2012, 12, 17), Value = 4 },
        new MyObject() { Key = 5, Day = new DateTime(2012, 12, 17), Value = 10 }
    };

私が探している結果は次のとおりです。

    List<MyObject> listChanges = new List<MyObject>()
    {
        new MyObject() { Key = 1, Day = new DateTime(2012, 12, 17), Value = -6 },
        new MyObject() { Key = 2, Day = new DateTime(2012, 12, 17), Value = -8 },
        new MyObject() { Key = 3, Day = new DateTime(2012, 12, 17), Value = 4 },
        new MyObject() { Key = 5, Day = new DateTime(2012, 12, 17), Value = 10 }
    };

基本的に、listA を listB にするために必要な変更を含むリストを作成しようとしています。したがって、LINQのExceptとIntersectを使用できますが、値の違いを得るには別の比較が必要になるため、そのようなタスクを実行するのに最高のパフォーマンスが得られるとは思いません。

私が考えたことの1つは、listAをループすると、listAとlistBからアイテムを削除できることです(見つかった場合、この時点で+/-の違いを判断できます)。listA を終了すると、listB には追加のみが含まれます。

変更結果を取得するにはどうすればよいですか?

4

3 に答える 3

0

これはどう :

        List<MyObject> listA = new List<MyObject>(){
            new MyObject() { Key = 1, Day = new DateTime(2012, 12, 17), Value = 8 },
            new MyObject() { Key = 2, Day = new DateTime(2012, 12, 17), Value = 8 },
            new MyObject() { Key = 1, Day = new DateTime(2012, 12, 18), Value = 8 },
            new MyObject() { Key = 4, Day = new DateTime(2012, 12, 17), Value = 4 },
            new MyObject() { Key = 3, Day = new DateTime(2012, 12, 17), Value = 4 }
        };

        List<MyObject> listB = new List<MyObject>(){
            new MyObject() { Key = 1, Day = new DateTime(2012, 12, 17), Value = 2 },
            new MyObject() { Key = 3, Day = new DateTime(2012, 12, 17), Value = 8 },
            new MyObject() { Key = 4, Day = new DateTime(2012, 12, 17), Value = 4 },
            new MyObject() { Key = 1, Day = new DateTime(2012, 12, 18), Value = 8 },
            new MyObject() { Key = 5, Day = new DateTime(2012, 12, 17), Value = 10 }
        };
        List<MyObject> listChanges = Comparer(listA, listB);
        MyObject[] hasil = listChanges.ToArray();
        for (int a = 0; a < hasil.Length;a++ ) {
            Console.WriteLine(hasil[a].Key+" "+hasil[a].Day+" "+hasil[a].Value);
        }

と関数:

    private MyObject[] sort(List<MyObject> input) {
        //sort input with it's key
        MyObject[] gg = input.ToArray();
        for (int a = 0; a < input.Count; a++) {
            for (int b = a + 1; b < input.Count; b++) {
                if (gg[a].Key > gg[b].Key) {
                    MyObject temp = gg[a];
                    gg[a] = gg[b];
                    gg[b] = temp;
                }
            }
        }
        //sort input, if key is same => sort the date
        for (int a = 0; a < input.Count; a++) {
            int indStart = a;
            int indEnd = a;
            for (int b = a + 1; b < input.Count; b++) {
                if (gg[a].Key == gg[b].Key) {
                    indEnd++;
                } else {
                    b = input.Count;
                }
            }
            a = indEnd;
            for (int c = indStart; c <= indEnd; c++) {
                for (int d = c + 1; d <= indEnd; d++) {
                    if (gg[c].Day > gg[d].Day) {
                        MyObject temp = gg[c];
                        gg[c] = gg[d];
                        gg[d] = temp;
                    }
                }
            }
        }
        return gg;
    }
    private List<MyObject> Comparer(List<MyObject> listA, List<MyObject> listB) {
        List<MyObject> output = new List<MyObject>();
        //if you sure that the list was sorted, u just remove the sort function
        MyObject[] ff = sort(listA);
        MyObject[] gg = sort(listB);
        Boolean[] masuk = new Boolean[gg.Length];
        //foreach element in listA, search the changes in input
        for (int a = 0; a < listA.Count;a++ ) {
            //find element in input which contains the changes of element in listA
            Boolean ins = false;
            for (int b = 0; b < listB.Count;b++ ) {
                if (masuk[b])
                    continue;
                if (ff[a].Key >= gg[b].Key) {
                    if (ff[a].Key == gg[b].Key && ff[a].Day == gg[b].Day){
                        masuk[b] = true;
                        if (gg[b].Value != ff[a].Value) {
                            output.Add(new MyObject() { Key = gg[b].Key, Day = gg[b].Day, Value = gg[b].Value - ff[a].Value });
                            b = listB.Count;
                        }
                        ins = true;
                    }
                } else {
                    b = listB.Count;
                }
            }
            if (!ins) {
                output.Add(new MyObject() { Key = ff[a].Key, Day = ff[a].Day, Value = -ff[a].Value });
            }
        }
        for (int a = 0; a < gg.Length;a++ ) {
            if(!masuk[a]){
                output.Add(new MyObject() { Key = gg[a].Key, Day = gg[a].Day, Value = gg[a].Value });
            }
        }
        return output;
    }

と出力:

    1 12/17/2012 12:00:00 AM -6
    2 12/17/2012 12:00:00 AM -8
    3 12/17/2012 12:00:00 AM 4
    5 12/17/2012 12:00:00 AM 10
于 2013-01-02T16:38:40.267 に答える
0

最初に、 プロパティとプロパティIEqualityComparer<T>の両方に基づいて等価性をチェックする を実装します。次に、次のように linq を使用できます。KeyDay

var notInA = listB.Except(listA, myEqualityComparer);
var notInB = listA.Except(listB, myEqualityComparer)
                   .Select(o => {
                      return new MyObject {
                         Key = item.Key,
                         Day = item.Day,
                         Value = item.Value * -1
                      };
                   });
var listA2 = listA.Intersect(listB, myEqualityComparer)
                  .OrderBy(o => o.Key)
                  .ThenBy(o => o.Day);
var listB2 = listB.Intersect(listA, myEqualityComparer)
                  .OrderBy(o => o.Key)
                  .ThenBy(o => o.Day);
var diff = listA2.Zip(listB2, (first,second) => {
   return new MyObject {
     Key = first.Key,
     Day = first.Day,
     Value = second.Value - first.Value
});
diff = diff.Concat(notInA).Concat(notInB);
于 2013-01-02T16:54:55.013 に答える
0

これでうまくいくはずです。Key/のDay組み合わせのいずれかが入力内で一意でない場合、例外がスローされます。

public static IEnumerable<MyObject> GetChanges(
    IEnumerable<MyObject> from, IEnumerable<MyObject> to)
{
    var dict = to.ToDictionary(mo => new { mo.Key, mo.Day });

    // Check that keys are distinct in from, too:
    var throwaway = from.ToDictionary(mo => new { mo.Key, mo.Day });

    // Adjustments of items found in "from"
    foreach (MyObject mo in from)
    {
        var key = new { mo.Key, mo.Day };
        MyObject newVal;
        if (dict.TryGetValue(key, out newVal))
        {
            // Return item indicating adjustment
            yield return new MyObject { 
                Key = mo.Key, Day = mo.Day, Value = newVal.Value - mo.Value };
            dict.Remove(key);
        }
        else
        {
            // Return item indicating removal
            yield return new MyObject {
                Key = mo.Key, Day = mo.Day, Value = -mo.Value };
        }
    }

    // Creation of new items found in "to"
    foreach (MyObject mo in dict.Values)
    {
        // Return item indicating addition
        // (Clone as all our other yields are new objects)
        yield return new MyObject {
            Key = mo.Key, Day = mo.Day, Value = mo.Value };
    }
}

一意性チェックを削除するか、オンザフライで実行することでこれを高速化できます(各アイテムのキーパーツを a に追加してみてください) 。辞書、一度残りを返します。fromHashSetto

于 2013-01-02T16:55:21.503 に答える