有没有更好的方法从另一个列表中删除项目?

时间:2018-01-13 16:24:00

标签: c# linq

我有一个包含myType类型对象的列表,并且第二个列表包含相同类型的对象。此对象具有ID属性,并且第一个列表中的对象与第二个列表中的项目不同。另外我知道在两个列表中,没有两个或更多具有相同ID的对象。

我想从第一个列表中删除ID在第二个列表中的项目,然后将第二个列表的项目添加到第一个列表中。

我在想这段代码:

    Dictionary<long, int> myDicIdWithPositionFirstList = new Dictionary<long, int>();
    for(int i = 0; i < myFirstList.Count; i++)
    {
        myDicIdWithPositionFirstList.Add(myFirstList[i].ID, i);
    }


    foreach (MyType iterator in mySecondList)
    {
        int myPosition = (myDicIdWithPositionFirstList.ContainsKey(iterator.ID) ? myDicIdWithPositionFirstList[iterator.ID] : -1;
        DgdOrdenesTrabajo.RemoveAt(myPosition);
        MyFirstList.Add(iterator);
    }

它的想法是用第一个列表的对象的ID和位置创建一个diccitionary。这具有O(n)复杂性。

稍后,我迭代第二个列表。我检查第一个列表中是否有。如果它在第一个列表中,我得到字典中的位置,即O(1),我从我知道的位置删除。

但我不知道这是不是一个好方法,或者有更好的方式,更简单,更快的性能。

感谢。

5 个答案:

答案 0 :(得分:1)

首先,如果列表包含唯一对象(唯一ID),那么请使用意味着唯一性的集合: Set if (data > 100 && data <= 20000) { otherValue = Math.ceil(data/1000)*10; } 作为不错的选择。

如果HashSet<MyObject>未根据MyObject实现值相等,则使用重载创建集合,以便您定义自定义ID

完成后,只需迭代第2组并检查每个对象是否包含在第1组中。如果是,则从第1组中删除并将第2组中的对象添加到第1组。

答案 1 :(得分:0)

如果目标是获得两个列表的并集,那么一种方法是使用Enumerable.Union,它使用默认的相等比较器。或者您可以在第二组中过滤掉重复项,然后将该过滤后的列表添加到第一个列表中。如,

MasterList.AddRange(SecondList.Where(i => !MasterList.Any(m => m.MyId == i.MyId)));

答案 2 :(得分:0)

您的方法是O(n),其中n MyFirstList 的大小 - 您在索引处删除元素,因此右侧部分始终被移位,因此它是{{1 }}。即使它是链表,RemoveAt也需要O(n)次。总的来说,您的实施是O(n)而不是天真的O(m*n)

更好的方法是不使用列表 - 使用二叉树,将 ID 作为键。因此,您的结构将存储在 SortedDictionary 中,而不是 List 和 单个项目的删除/更新/创建将采用O(m*(n+1)),两个集合同步将采用O(log(n))

O(m*log(n))

<强> PS

您实际上不需要显式删除,因为您添加了新元素作为替换。因此,您只需更新指定索引处的值,而不是删除它,否则添加:

var myFirstDictionary = new SortedDictionary(myFirstList.Count);
foreach(var item in myFirstList)
{
    myFirstDictionary[item.Id] = item;
}
//updating/creating values in first list by using second list values
foreach(var item in mySecondList)
{
    myFirstDictionary[item.Id] = item;
}

答案 3 :(得分:0)

尝试下面的内容,列出第一个列表中未包含的所有项目

var result = DgdOrdenesTrabajo.FindAll(v => !mySecondList.FindAll(var=>myFirstList.Any(var1=>(var1.ID==var.ID)))
                                                         .Any(v2=>v2.ID==v.ID)).ToList<MyType>();

答案 4 :(得分:0)

如果我没有弄错的话,听起来你只需要一个独特的联盟

  

我想从第一个列表中删除ID在第二个列表中的项目,然后将第二个列表的项目添加到第一个列表中。

void Main()
{
    var first = new []
    {
        new MyType{Id = 11, Name = "John"},
        new MyType{Id = 12, Name = "Jack"},
        new MyType{Id = 13, Name = "Jim"},
        new MyType{Id = 14, Name = "Joel"},
        new MyType{Id = 15, Name = "Jay"},
    };

    var second = new[]
    {
        new MyType{Id = 21, Name = "Jake"},
        new MyType{Id = 22, Name = "Jan"},
        new MyType{Id = 13, Name = "Jim"},
        new MyType{Id = 14, Name = "Joel"},
        new MyType{Id = 23, Name = "Jane"},
        new MyType{Id = 24, Name = "Jade"},
    };

    var results = first
        .Union(second)
        .Distinct(new MyTypeComparer());
    results.Dump();

    //11 John
    //12 Jack
    //13 Jim
    //14 Joel
    //15 Jay
    //21 Jake
    //22 Jan
    //23 Jane
    //24 Jade
}

public class MyType
{
    public int Id { get; set; }
    public string Name { get; set; }
}

public class MyTypeComparer : IEqualityComparer<MyType>
{
    public bool Equals(MyType x, MyType y)
    {
        return x.Id == y.Id;
    }

    public int GetHashCode(MyType obj)
    {
        return obj.Id ^ 13;
    }
}