C# 使用LINQ取消数据结构的平台化
这不是一个家庭作业问题。如果需要的话,请随意推荐一个更好的地方来发布 鉴于以下数据结构:C# 使用LINQ取消数据结构的平台化,c#,linq,C#,Linq,这不是一个家庭作业问题。如果需要的话,请随意推荐一个更好的地方来发布 鉴于以下数据结构: class Thing { public Thing() { this.Things = new List<Thing>(); } public string First { get; set; } public string Group { get; set; } public List<Thing> Thing
class Thing
{
public Thing()
{
this.Things = new List<Thing>();
}
public string First { get; set; }
public string Group { get; set; }
public List<Thing> Things { get; set; }
}
需要注意的一些事项:
- 请注意,事物可以包含事物列表李>
- 如果未指定First,则假定为父项,并且包含具有相同组的First的所有记录都是子项
- 根据上述规则,没有父项的记录被视为父项
var result = data.Where(p => p.First == "").Select(p =>
{
p.Things = data.Where(f => f.Group == p.Group).ToList();
return p;
}).ToList();
result.AddRange(data.Except(result.SelectMany(f => f.Things)).ToList());
这也达到了预期的效果,但感觉有点长
var result = data
.GroupBy(p => p.Group)
.SelectMany(p => p.Where(f => f.First == "" || p.Count() == 1))
.Select(p => new Thing { First = p.First, Group = p.Group, Things = data
.Where(f => f.Group == p.Group && f.First != "" && p.First != f.First).ToList() });
没有错误检查或其他考虑的功能
static void Main(string[] args)
{
var data = new List<Thing> { new Thing { First = "Alex", Group = "Sams" }, new Thing { First = "John", Group = "Sams" }, new Thing { First = "", Group = "Sams" }, new Thing { First = "Sue", Group = "Freds" } };
var results = from item in data
group item by item.Group into g
select g;
List<Thing> list = new List<Thing>();
foreach (var item in results)
{
if (item.Count() > 1)
{
Thing parent = item.Where(x => String.IsNullOrEmpty(x.First)).First();
parent.First = "";
parent.Group = item.First().Group;
parent.Things = item.Where(x => x != parent).ToList();
list.Add(parent);
}
else
{
list.Add(item.First());
}
}
}
static void Main(字符串[]args)
{
var data=new List{new Thing{First=“Alex”,Group=“Sams”},new Thing{First=“John”,Group=“Sams”},new Thing{First=”,Group=“Sams”},new Thing{First=“Sue”,Group=“Freds”};
var结果=来自数据中的项
逐项分组。分组为g
选择g;
列表=新列表();
foreach(结果中的var项目)
{
如果(item.Count()>1)
{
Thing parent=item.Where(x=>String.IsNullOrEmpty(x.First)).First();
父项。第一个=”;
parent.Group=item.First().Group;
parent.Things=item.Where(x=>x!=parent.ToList();
列表。添加(父级);
}
其他的
{
list.Add(item.First());
}
}
}
一句话是。。。由于有多个枚举,所以效率更高
var unflattenedList = data.GroupBy(thing => thing.Group, thing => thing,
(key, things) => new Thing()
{
First = things.Count() == 1 ? things.First().First : string.Empty,
Group = key,
Things = things.Count() == 1 ? null :
things.Where(t => t.First != string.Empty).ToList(),
});
编辑:
然而,以下是我将使用的内容。。因为这消除了上述解决方案的多重枚举问题
你的LINQ是这样的
var unflattenedList = data.GroupBy(thing => thing.Group, thing => thing, GetThing);
您返回新事物的方法在这里
private static Thing GetThing(string key, IEnumerable<Thing> things)
{
var thingList = things.ToList();
return new Thing()
{
First = thingList.Count() == 1 ? thingList.First().First : string.Empty,
Group = key,
Things = thingList.Count() == 1 ? null :
thingList.Where(t => t.First != string.Empty).ToList(),
};
}
私有静态对象获取(字符串键、IEnumerable对象)
{
var thingList=things.ToList();
返回新事物()
{
First=thingList.Count()==1?thingList.First()。First:string.Empty,
组=键,
Things=thingList.Count()==1?空:
thingList.Where(t=>t.First!=string.Empty).ToList(),
};
}
这似乎很好:
var result =
data
.Where(p => p.First != "")
.GroupBy(p => p.Group)
.Select(gps =>
gps.Count() == 1
? gps.First()
: new Thing()
{
First = "",
Group = gps.Key,
Things = gps.ToList(),
})
.ToList();
这基本上会忽略所有先有的现有内容==”
,然后按组对所有剩余内容进行分组。然后,它用一个新的父对象重新构建列表,其中组具有多个内容
在存在没有子对象的“父”对象的情况下,这里有一个更健壮的替代方案:
var result2 =
data
.GroupBy(p => p.Group)
.Select(gps =>
gps.Count() == 1
? gps.First()
: new Thing()
{
First = "",
Group = gps.Key,
Things =
gps
.Where(p => p.First != "")
.ToList(),
})
.ToList();
只有一个层次还是多个层次的东西?好吧,父母和孩子,但没有比这更深的东西。是的,我尝试了很多东西,但它会填满很多页面,只是炫耀我的其他尝试。我知道有一百种方法可以做到这一点。。只是好奇其他人认为什么是最好的方式。你怎么能期望一个列表像那样缩进?我不确定输出格式是什么?它们是对象还是文本输出?您应该至少显示一个失败的尝试。一些你认为是你最好的尝试。这有助于我们回答这个问题。这不符合要求,因为它将父Sams行作为自身的子行包含在内。所以Sams的父级应该只有两个子级,这就解决了这个问题。这与我在OP中的最后一个示例在输出方面的最大区别是,Freds行包含一个空的子集合。没什么大不了的,真的。你和我的个人偏好是什么?都不是。。。我会写一个小方法,把小组变成一个新的东西()这也很有效,而且非常聪明。跳出框框思考得很好。+1做得好。我原以为这会导致groupby IEnumerable的多次枚举,但R#不这么认为,而且我想不出一种方法来测试它是否会。使用GroupBy selectResults函数肯定可以。@Kevin-谢谢。:-)什么是R#?
var result =
data
.Where(p => p.First != "")
.GroupBy(p => p.Group)
.Select(gps =>
gps.Count() == 1
? gps.First()
: new Thing()
{
First = "",
Group = gps.Key,
Things = gps.ToList(),
})
.ToList();
var result2 =
data
.GroupBy(p => p.Group)
.Select(gps =>
gps.Count() == 1
? gps.First()
: new Thing()
{
First = "",
Group = gps.Key,
Things =
gps
.Where(p => p.First != "")
.ToList(),
})
.ToList();