我有一个列表,我试图从另一个列表中填充,我想在其中组合一些数据并消除一些数据。
在原始列表中,数据如下所示:
Id Text Description
1 Apple Red Delicious
1 Apple Green
1 Apple Granny
2 Tomato Roma
2 Tomato Cherry
我想在第二个列表中压缩这些信息,如下所示:
Id Text Description
1 Apple Red Delicious, Green, Granny
2 Tomato Roma, Cherry
我的类对象声明如下:
[Serializable]
public class Food
{
public int Id { get;set; }
public string Text { get;set; }
public string Description { get;set; }
}
所以我想遍历旧列表,这就是我在代码中尝试这样做的方式:
var ids = oldList.Select(i => i.Id).Distinct(); //get distinct list of ids (e.g. 1,2)
List<Food> newList = ids.Select(i => new Food(){
Id = i,
Text = oldList.Where(o => o.Id == i).Select(o => o.Text).Take(1).ToString(),
Description = string.Join(",", oldList.Where(o => o.Id == i).Select(o => o.Description).ToString())
}).ToList();
现在我因为.Take()而得到System.Linq.Enumerable + d__3a`1 [System.String]错误,但是如果我只更改它.ToString(),我会得到一个稍微不同的错误但是来自同一个源System.linq.Enumerable,如果我做FirstOrDefault()同样的事,.Distinct()同样的事情。
我想我明白问题是对于Text和Description它返回文本和描述的IEnumerable所以我没有得到我想要的实际值,我不确定我是否理解如何正确转换它.ToList ()。访问这些值的正确方法是什么?
答案 0 :(得分:5)
您正在ToString()
和Take
的结果上调用Select
- 并且这不会做任何好事。我不清楚为什么您在ToString
中明确调用Description
,而Text
您真正想要FirstOrDefault
或First
而是,因为您只想要第一个结果:
List<Food> newList = ids.Select(i => new Food {
Id = i,
Text = oldList.Where(o => o.Id == i).Select(o => o.Text).FirstOrDefault(),
Description = string.Join(",", oldList.Where(o => o.Id == i)
.Select(o => o.Description))
}).ToList();
基本上,在序列(ToString()
)上调用IEnumerable<T>
几乎永远不适合
答案 1 :(得分:1)
这是GroupBy
运营商的典型工作:
var newList = oldList.GroupBy(x => x.Id,
(key, values) =>
new Food() {
Id = key,
Text = values.First().Text,
Description = string.Join(", ",
values.Select(v => v.Description))
})
.SelectMany(x => x)
.ToList();
答案 2 :(得分:1)
我认为你的方法可能过于复杂。
这是一个非常粗略的黑客攻击样本(如果你愿意,你可以在LinqPad中运行它),但它使用.GroupBy
来解决同样的问题......
var l = new List<Tuple<int, string, string>>();
l.Add(Tuple.Create(1, "Apple", "Red Delicious"));
l.Add(Tuple.Create(1, "Apple", "Green"));
l.Add(Tuple.Create(1, "Apple", "Granny"));
l.Add(Tuple.Create(2, "Tomato", "Roma"));
l.Add(Tuple.Create(2, "Tomato", "Cherry"));
var res = l.GroupBy(t => t.Item2).Select(g => new { Id = g.First().Item1, Text = g.Key, Description = string.Join(", ", g.Select(i => i.Item3)) });
res.Dump(); // Linqpad output