c#基于公共属性合并来自两个(或更多)列表的属性
本文关键字:属性 两个 列表 于公共 合并 | 更新日期: 2023-09-27 18:18:44
我有三个对象列表,每个对象列表通过以下层次结构中的单个公共属性Parent
和Node
链接到另一个列表:模型->中间->结果。我有以下代码:
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.Node
和intermediate.Parent
链接到Intermediate
对象,Intermediate
对象通过intermediate.Node
和results.Parent
链接到Results
对象。请注意,列表可以包含数千个项目,每个项目都使用与上面类似的格式添加。
我想要做的是将列表中Model
对象的名称添加到results
列表中匹配的Results
对象。
我的想法是,我可以循环遍历Intermediate
列表中的每个对象,并找到(使用LINQ) Result
对象,其中intermediate.Node = result.Parent
,然后用intermediate.Parent
替换result.Parent
的值,或者向Result
对象添加一个新的Grandparent
属性,以放置intermediate.Parent
。然后重复这个过程,循环遍历models
列表中的每个对象,找到匹配的Result
对象并添加Name
。
所以我想我的问题是,这是最好的方法吗,还是有更有效的方法?我有许多列表,其中相同的将不得不重复,所以我想知道是否有一个更好的方法,因为它可以相当缓慢地循环遍历每个对象。是否有一种方法可以从第一个列表直接获取到第三个列表。
我希望这是足够好的解释。对于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();
}
}