如何比较两个列表并更改一个属性

时间:2017-02-01 10:50:52

标签: c# linq

我有一个班级:

public class Doc
{
   public int Id {get; set;}
   public string Name {get; set;}
   public bool IsActive {get; set;}
}

两个Doc类型的列表。

如果包含来自第二个列表的id,如何编写LINQ来比较这些列表并更改第一个列表的IsActive属性。

5 个答案:

答案 0 :(得分:4)

鉴于您的目标列表名为targetDocs,并且您要检查文档存在的列表是srcDocs,请尝试类似的内容(无法访问编译器,因此可以&#39 ; t test):

targetDocs.ForEach(d => d.IsActive = srcDocs.Any(sd => sd.id == d.Id))

我假设我们正在谈论List而不是其他集合类型,因为为List定义了ForEach扩展方法。

答案 1 :(得分:1)

最好将HashSet<T>集合用于此类操作,它具有快速O(1)查找,并且没有真正的理由在此处使用LINQ来更改属性值。没错,我们必须在这里创建另一个集合,并且需要时间来分配资源来初始化它等等。但是如果有一百万条记录,它将会带来巨大的性能提升。

如果docs2集合具有Id,则docs1是您希望将IsActive更改为true的集合,您可以使用:

var ids = new HashSet<int>(docs2.Select(d => d.Id));
foreach(var doc in docs1) 
{
                  // .Contains implementation in HashSet has fast O(1) lookups
   doc.IsActive = ids.Contains(doc.Id); 
}

答案 2 :(得分:0)

您可以创建自己的静态方法,该方法负责检查活动属性。我在这里使用了枚举器,它工作起来快速且易于理解。

static class Program
{

    static void Main(string[] args)
    {
        List<Data> firstInstance = new List<Data>
        {
            new Data { Id = 1, IsActive = false },
            new Data { Id = 2, IsActive = false }
        };

        List<Data> secondInstance = new List<Data>
        {
            new Data { Id = 1, IsActive = false },
            new Data { Id = 3, IsActive = false }
        };

        firstInstance.CheckActive(secondInstance);
    }

    static void CheckActive(this List<Data> firstInstance, List<Data> secondInstance)
    {
        using (IEnumerator<Data> firstEnumerator = firstInstance.GetEnumerator(), secondEnumerator = secondInstance.GetEnumerator())
        {
            while (true)
            {
                if (!firstEnumerator.MoveNext() || !secondEnumerator.MoveNext()) break;
                if (firstEnumerator.Current.Id == secondEnumerator.Current.Id) firstEnumerator.Current.IsActive = true;
            }
        }
    }
}

class Data
{
    public int Id { get; set; }
    public bool IsActive { get; set; }
}

答案 3 :(得分:0)

您写道:

  

如何编写linq来比较这些列表并更改&#34; IsActive&#34;如果包含来自第二个列表的id,则第一个列表的符号。

您的第一个列表没有IsActive属性,但列表中的元素有一个。因此,我假设您需要以下内容:

  

如何获取第一个列表中所有元素的序列,其中第二个列表中包含任何元素的Id,因此我可以更改这些元素的IsActive属性。

LINQ用于枚举对象。您无法更改linq语句中的对象

如果要更改对象,则必须对它们进行枚举,例如使用ForEach。

IEnumerable<int> activeIds = secondList.Select(item => item.Id);
IEnumerable<Doc> activeDocs = firstList.Where(item => activedIds.Contains(item.Id));

foreach (Doc activeDoc in activeDocs)
{
    activeDoc.IsActive = true;
}

注意:我没有为所有inActive文档更改ISActive。如果你想要,你必须预先知道firstList中的所有元素:

IEnumerable<int> activeIds = secondList.Select(item => item.Id);
foreach (Doc doc in firstList)
{
    doc.IsActive = activeIds.Contains(doc.Id);
}

答案 4 :(得分:-1)

您可以在不使用linq的情况下使用此解决方案

foreach(Doc x in list1){ 
  foreach(Doc y in list2){
    if(x.id == y.id){
       y.IsActive = true;
                    }
                        }
                      }