c#组合列表并将项目标记为已找到

本文关键字:记为 目标 项目 组合 列表 | 更新日期: 2023-09-27 18:02:44

我有一个类:

public class Item
{
    public string Name { get; set; }
    public bool IsFound { get; set; }
}

和2个列表:

List<Item> first = new List<Item>();
List<Item> second = new List<Item>();
  • First列表包含一些预定义的唯一项目
  • Second列表还包含一些独特的项目

如何根据Name属性将第二个列表项添加到第一个列表中而不重复,忽略大小写?

c#组合列表并将项目标记为已找到

second中的项目添加到现有的first列表中:

  List<Item> first = new List<Item>();
  List<Item> second = new List<Item>();
  ... 
  // ids to exclude while adding
  HashSet<String> ids = new HashSet<string>(first.Select(item => item.Name),
    StringComparer.InvariantCultureIgnoreCase);
  // add all items from the second, except exluded 
  first.AddRange(second.Where(item => !ids.Contains(item.Name)));

这是一个使用HashSet`1IEquatable`1的工作解决方案。如果你需要使用List`1,你可以使用Ned Stoyanov的答案中指出的Linq。

代码

class Program {
    static void Main(string[] args) {
        var first = new HashSet<Item>() {
            new Item() { Name = "a" },
            new Item() { Name = "b" },
        };
        var second = new HashSet<Item>() {
            new Item() { Name = "b" },
            new Item() { Name = "c" },
        };
        var both = first.Union(second).ToList();
        both.ForEach(Console.WriteLine);
        Console.ReadKey();
    }
}
public class Item : IEquatable<Item> {
    public string Name { get; set; }
    public bool IsFound { get; set; }
    public override bool Equals(object that) {
        return that is Item && this.Equals((Item)that);
    }
    public bool Equals(Item that) {
        return this.Name.Equals(that.Name, StringComparison.InvariantCultureIgnoreCase);
    }
    public override int GetHashCode() {
        return Name.GetHashCode();
    }
    public override string ToString() {
        return Name;
    }
}

输出:

a
b
c

注意:由于HashSet`1 s的实现,元素的顺序不受尊重。

First.Union(Second).GroupBy(x=>x.Name).Select(x=>x.FirstOrDefault());

如果你事先知道你的列表有唯一的项目,为什么它们不是ISet<项目>?这正是ISet的用途。一旦您将它们更改为ISet,您可以简单地调用:

first.UnionWith(second);

如果您实现了IEqualityComparer<Item>或更好的版本,请使用此答案中的KeyEqualityComparer。您可以使用Linq Union来获得您的结果。

first.Union(second, new KeyEqualityComparer( i => i.Name));

如果没有,我如何将第二个列表项添加到第一个列表是否基于Name属性重复,忽略大小写?

这是你想要的:

List<Item> third = first.Concat(second)
    .GroupBy(i => i.Name, StringComparer.InvariantCultureIgnoreCase)
    .Select(g => new Item
    {
        Name = g.Key,
        IsFound = g.Count() > 1
    })
    .ToList();

g.Count() > 1仅适用于来自不同列表的具有相同名称(忽略大小写(的项目,因此g.Count()为1或2。

这应该做到:

var distinct = from item in second
               where first.All(x => !String.Equals(x.Name, item.Name, StringComparison.OrdinalIgnoreCase))
               select item;
first.AddRange(distinct);

您可以有一个组合列表,其中只添加第二个列表中缺少的项。

   class Program
    {
        static void Main(string[] args)
        {
            var first = new List<Item> { new Item("one"), new Item("two") };
            var second = new List<Item> { new Item("two"), new Item("three") };
            var combined = new List<Item>();
            combined.AddRange(first);
            foreach (var item in second)
            {
                int index = combined.FindIndex(x => x.name == item.name);
                if (index <= 0)
                {
                    combined.Add(item);
                }
            }
            foreach (var item in combined)
            {
                Console.WriteLine(item.name);
            }
        }
        class Item
        {
            public string name;
            public Item(string name)
            {
                this.name = name;
            }
        }
    }