한 목록을 다른 목록으로 업데이트하는 데 필요한 코드의 양은 얼마입니까?

StackOverflow https://stackoverflow.com/questions/148662

문제

목록이 하나 있다고 가정 해

IList<int> originalList = new List<int>();
originalList.add(1);
originalList.add(5);
originalList.add(10);

그리고 다른 목록 ...

IList<int> newList = new List<int>();
newList.add(1);
newList.add(5);
newList.add(7);  
newList.add(11);

다음과 같이 원인을 업데이트 할 수있는 방법은 다음과 같습니다.

  1. int가 Newlist에 나타나면 유지하십시오
  2. int가 Newlist에 나타나지 않으면 제거하십시오.
  3. Newlist의 int를 아직 존재하지 않는 Originallist에 추가하십시오.

따라서 - Originallist의 내용을 만들기 :

{ 1, 5, 7, 11 }

내가 묻는 이유는 자녀 모음이있는 물건이 있기 때문입니다. 사용자가 모든 어린이를 삭제 한 다음 선택을 삽입하는 대신이 컬렉션을 업데이트 할 때 전체 컬렉션을 찢어 내지 않고 추가하거나 제거 된 어린이들에게 방금 행동하면 더 효율적이라고 생각합니다. 마치 마치 마치 마치 마치 마치 마치 마치 마치 모두 새 것처럼.

편집 - 죄송합니다 - 나는 끔찍한 제목을 썼습니다 ... 나는 '효율적인'대신 '최소한 양의 코드'를 썼어야합니다. 나는 내가 얻은 답을 많이 버렸다고 생각합니다. 그들은 모두 훌륭합니다 ... 감사합니다!

도움이 되었습니까?

해결책

죄송합니다. 마지막 단락을보기 전에 첫 번째 응답을 썼습니다.

for(int i = originalList.length-1; i >=0; --i)
{
     if (!newList.Contains(originalList[i])
            originalList.RemoveAt(i);
}

foreach(int n in newList)
{
     if (!originaList.Contains(n))
           originalList.Add(n);
}

다른 팁

originalList = newList;

또는 당신이 그것들이 뚜렷한 목록을 선호하는 경우 :

originalList = new List<int>(newList);

그러나 어느 쪽이든 당신이 원하는 것을 수행합니다. 귀하의 규칙에 따라, 업데이트 후 Originallist는 Newlist와 동일합니다.

업데이트 :이 답변을 지원해 주셔서 감사합니다. 그러나 질문을 면밀히 읽은 후에는 내 다른 응답이 올바른 것입니다.

LINQ 확장 메소드를 사용하는 경우 두 줄로 수행 할 수 있습니다.

originalList.RemoveAll(x => !newList.Contains(x));
originalList.AddRange(newList.Where(x => !originalList.Contains(x)));

이것은 다른 사람들의 솔루션과 마찬가지로 원래 대상에서 상인이 상인이라고 가정합니다. 그러나 어떤 이유로 같은 이유를 재정의 할 수 없다면 다음과 같은 iequalityOperator를 만들 수 있습니다.

class EqualThingTester : IEqualityComparer<Thing>
{
    public bool Equals(Thing x, Thing y)
    {
        return x.ParentID.Equals(y.ParentID);
    }

    public int GetHashCode(Thing obj)
    {
        return obj.ParentID.GetHashCode();
    }
}

위의 줄은 다음과 같습니다.

originalList.RemoveAll(x => !newList.Contains(x, new EqualThingTester()));
originalList.AddRange(newList.Where(x => !originalList.Contains(x, new EqualThingTester())));

그리고 어쨌든 iequalityOperator를 통과한다면 두 번째 줄을 더 짧게 만들 수 있습니다.

originalList.RemoveAll(x => !newList.Contains(x, new EqualThingTester()));
originalList.AddRange(newList.Except(originalList, new EqualThingTester()));

최종 주문에 대해 걱정하지 않으면 해시 가능/해시 세트가 가장 빠릅니다.

LINQ solution:

originalList = new List<int>(
                      from x in newList
                      join y in originalList on x equals y into z
                      from y in z.DefaultIfEmpty()
                      select x);

My initial thought was that you could call originalList.AddRange(newList) and then remove the duplicates - but i'm not sure if that would be any more efficient than clearing the list and repopulating it.

List<int> firstList = new List<int>() {1, 2, 3, 4, 5};
List<int> secondList = new List<int>() {1, 3, 5, 7, 9};

List<int> newList = new List<int>();

foreach (int i in firstList)
{
  newList.Add(i);
}

foreach (int i in secondList)
{
  if (!newList.Contains(i))
  {
    newList.Add(i);
  }
}

Not very clean -- but it works.

There is no built in way of doing this, the closest I can think of is the way DataTable handles new and deleted items.

What @James Curran suggests is merely replace the originalList object with the newList object. It will dump the oldList, but keep the variable (i.e. the pointer is still there).

Regardless, you should consider if optimising this is time well spent. Is the majority of the run time spent copying values from one list to the next, it might be worth it. If it's not, but rather some premature optimising you are doing, you should ignore it.

Spend time polishing the GUI or profile the application before you start optimising is my $.02.

This is a common problem developers encounter when writing UIs to maintain many-to-many database relationships. I don't know how efficient this is, but I wrote a helper class to handle this scenario:

public class IEnumerableDiff<T>
{
    private delegate bool Compare(T x, T y);

    private List<T> _inXAndY;
    private List<T> _inXNotY;
    private List<T> _InYNotX;

    /// <summary>
    /// Compare two IEnumerables.
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="compareKeys">True to compare objects by their keys using Data.GetObjectKey(); false to use object.Equals comparison.</param>
    public IEnumerableDiff(IEnumerable<T> x, IEnumerable<T> y, bool compareKeys)
    {
        _inXAndY = new List<T>();
        _inXNotY = new List<T>();
        _InYNotX = new List<T>();
        Compare comparer = null;
        bool hit = false;

        if (compareKeys)
        {
            comparer = CompareKeyEquality;
        }
        else
        {
            comparer = CompareObjectEquality;
        }


        foreach (T xItem in x)
        {
            hit = false;
            foreach (T yItem in y)
            {
                if (comparer(xItem, yItem))
                {
                    _inXAndY.Add(xItem);
                    hit = true;
                    break;
                }
            }
            if (!hit)
            {
                _inXNotY.Add(xItem);
            }
        }

        foreach (T yItem in y)
        {
            hit = false;
            foreach (T xItem in x)
            {
                if (comparer(yItem, xItem))
                {
                    hit = true;
                    break;
                }
            }
            if (!hit)
            {
                _InYNotX.Add(yItem);
            }
        }
    }

    /// <summary>
    /// Adds and removes items from the x (current) list so that the contents match the y (new) list.
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    /// <param name="compareKeys"></param>
    public static void SyncXList(IList<T> x, IList<T> y, bool compareKeys)
    {
        var diff = new IEnumerableDiff<T>(x, y, compareKeys);
        foreach (T item in diff.InXNotY)
        {
            x.Remove(item);
        }
        foreach (T item in diff.InYNotX)
        {
            x.Add(item);
        }
    }

    public IList<T> InXAndY
    {
        get { return _inXAndY; }
    }

    public IList<T> InXNotY
    {
        get { return _inXNotY; }
    }

    public IList<T> InYNotX
    {
        get { return _InYNotX; }
    }

    public bool ContainSameItems
    {
        get { return _inXNotY.Count == 0 && _InYNotX.Count == 0; }
    }

    private bool CompareObjectEquality(T x, T y)
    {
        return x.Equals(y);
    }

    private bool CompareKeyEquality(T x, T y)
    {
        object xKey = Data.GetObjectKey(x);
        object yKey = Data.GetObjectKey(y);
        return xKey.Equals(yKey);
    }

}

if your using .Net 3.5

var List3 = List1.Intersect(List2);

Creates a new list that contains the intersection of the two lists, which is what I believe you are shooting for here.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top