c#基于公共属性合并来自两个(或更多)列表的属性

本文关键字:属性 两个 列表 于公共 合并 | 更新日期: 2023-09-27 18:18:44

我有三个对象列表,每个对象列表通过以下层次结构中的单个公共属性ParentNode链接到另一个列表:模型->中间->结果。我有以下代码:

class Result
{
    public string Name { get; set; }
    public int Node{ get; set; }
    public int Parent{ get; set; }
}
class Intermediate
{
    public int Node{ get; set; }
    public int Parent{ get; set; }
}
class Model
{
    public string Name { get; set; }
    public int Node{ get; set; }
    public int Parent{ get; set; }
}
public class Example
{
    public static void Main()
    {
        List<Result> results = new List<Result>();
        List<Intermediate> intermediates = new List<Intermediate>();
        List<Model> models = new List<Model>();
        // Example objects in the list
        results.Add(new Result() { Name = "", Parent = 21, Node = 101 });
        intermediates.Add(new Part() { Parent = 11, Node = 21 });
        models.Add(new Part() { Name = "ABCD", Parent = 1, Node = 11 });
        ...
    }
}

可以看出,Model对象通过model.Nodeintermediate.Parent链接到Intermediate对象,Intermediate对象通过intermediate.Noderesults.Parent链接到Results对象。请注意,列表可以包含数千个项目,每个项目都使用与上面类似的格式添加。

我想要做的是将列表中Model对象的名称添加到results列表中匹配的Results对象。

我的想法是,我可以循环遍历Intermediate列表中的每个对象,并找到(使用LINQ) Result对象,其中intermediate.Node = result.Parent,然后用intermediate.Parent替换result.Parent的值,或者向Result对象添加一个新的Grandparent属性,以放置intermediate.Parent。然后重复这个过程,循环遍历models列表中的每个对象,找到匹配的Result对象并添加Name

所以我想我的问题是,这是最好的方法吗,还是有更有效的方法?我有许多列表,其中相同的将不得不重复,所以我想知道是否有一个更好的方法,因为它可以相当缓慢地循环遍历每个对象。是否有一种方法可以从第一个列表直接获取到第三个列表。

我希望这是足够好的解释。对于c#,我还是个初学者。

c#基于公共属性合并来自两个(或更多)列表的属性

实际上是Results -> Intermediate -> Model而不是Model -> Intermediate -> Results。

为了加快删除Intermediate的过程,构建一个字典。然后,您可以使用字典对结果进行简单的选择以进行转换。

var intermediateDict=intermediates.ToDictionary(key=>key.Node,val=>val.Parent);
var newresults=results.Select(r=>new Result {
  Name=r.Name,
  Node=r.Node,
  Parent=intermediateDict[r.Parent]
  });

你也可以通过join来得到最终答案

看起来可以使用foreach循环获取结果(叶)节点并将模型名称分配给结果节点:

var theModel = models.First(); // select a model
foreach (var interm in intermediates.Where(x => x.Parent == theModel.Node))
{
    foreach (var res in results.Where(x => x.Parent == interm.Node))
    {
        res.Name = theModel.Name;
    }
}

闻起来像你在这里说的复合模式。

你可以使用HashSet保存你的值来快速执行。

public class Item
{
    public Item(int itemNode)
    {
        Node = itemNode;
        Children = new HashSet<Item>();
    }
    public int Node { get; set; }
    public Item Parent { get; set; }
    private HashSet<Item> Children { get; set; }
    public bool Add(Item item)
    {
        item.Parent = this;
        return Children.Add(item);
    }
    public List<Item> Find(Func<Item, bool> predicate)
    {
        var found = new List<Item>();
        if (predicate(this)) found.Add(this);
        Collect(predicate, found);
        return found;
    }
    public void Collect(Func<Item, bool> predicate, List<Item> collected = null)
    {
        collected = collected ?? new List<Item>();
        collected.AddRange(Children.Where(predicate).ToList());
        foreach (var child in Children)
        {
            child.Collect(predicate, collected);
        }
    }
}
public class Model : Item //this is your model
{
    public string Name { get; set; }
    public Model(int itemNode, string name) : base(itemNode)
    {
        Name = name;
    }
    public List<Item> GetNamesMatchingWith(Func<Item, bool> predicate)
    {
        return Find(predicate);
    }
}
public class Example
{
    public static void Main()
    {
        var root = new Model(0, "root");
        var one = new Model(1, "1");
        var two = new Model(2, "2");
        var tree = new Model(3, "3");
        root.Add(one);
        root.Add(two);
        root.Add(tree);
        var a = new Model(4, "a");
        var b = new Model(5, "b");
        two.Add(a);
        two.Add(b);
        var namesMatchingWith = root.GetNamesMatchingWith(x=> x.Parent!=null && x.Parent.Node == 2);
        Console.ReadKey();
    }
}