使用Linq选择查询并新建对象。

52
我有一个Linq查询。
var x = (from t in types select t).GroupBy(g =>g.Type)

这个功能是按照对象类型对它们进行分组,因此我想要一个包含所有分组对象及其数量的新对象。类似于这样:

type1, 30    
type2, 43    
type3, 72

为了更加明确:结果分组应该在一个对象中,而不是每种项目类型一个对象。
6个回答

64

这里的答案让我接近了解决方法,但是在2016年,我能够使用以下的LINQ代码:

List<ObjectType> objectList = similarTypeList.Select(o =>
    new ObjectType
    {
        PropertyOne = o.PropertyOne,
        PropertyTwo = o.PropertyTwo,
        PropertyThree = o.PropertyThree
    }).ToList();

50
在Microsoft MSDN网站上阅读:101 LINQ SamplesLINQ - Grouping Operators
var x = from t in types  group t by t.Type
         into grp    
         select new { type = grp.key, count = grp.Count() };

对于单个对象,可以使用 StringBuilder 并将其附加,或将其转换为字典形式:
    // fordictionary 
  var x = (from t in types  group t by t.Type
     into grp    
     select new { type = grp.key, count = grp.Count() })
   .ToDictionary( t => t.type, t => t.count); 

   //for stringbuilder not sure for this 
  var x = from t in types  group t by t.Type
         into grp    
         select new { type = grp.key, count = grp.Count() };
  StringBuilder MyStringBuilder = new StringBuilder();

  foreach (var res in x)
  {
       //: is separator between to object
       MyStringBuilder.Append(result.Type +" , "+ result.Count + " : ");
  }
  Console.WriteLine(MyStringBuilder.ToString());   

41

你是想要分组的所有对象,还是所有类型?看起来你可能只需要:

var query = types.GroupBy(t => t.Type)
                 .Select(g => new { Type = g.Key, Count = g.Count() });

foreach (var result in query)
{
    Console.WriteLine("{0}, {1}", result.Type, result.Count);
}

编辑:如果你希望它成为一个字典,你可以直接使用:

var query = types.GroupBy(t => t.Type)
                 .ToDictionary(g => g.Key, g => g.Count());

不需要先选择成对,再建立字典。


抱歉问题描述不清楚。您的解决方案非常接近我需要的,但是我希望将所有分组结果放在单个对象中,而不是每种类型的一个对象。 - Jeff
1
@Jeff:你接受的答案实际上与我的相同...只是在字典中。结果都在一个单一对象(query)中。仍然不清楚您想要实现什么,而我的解决方案对您来说并没有做到这一点。如果您要按类型分组,那么每个组必须有一个对象,但是在这里,“查询”是将给您所有这些组的查询。 - Jon Skeet
我知道在分组列表中我将要查找哪些类型,因此将其放在字典中似乎很容易创建一个查询之外的对象。 - Jeff
@Jeff:所以你确实想要一个字典吗?(这仍然不是很清楚...)如果你想要一个字典,那没问题-看看我的编辑,有一种比被接受的答案稍微简单一点的构建字典的方法。 - Jon Skeet
这与我预期的有些不同,但由于我可以将它放入字典中,足以解决我的问题。非常感谢您的帮助。 - Jeff

4
var x = from t in types
        group t by t.Type into grouped
        select new { type = grouped.Key,
                     count = grouped.Count() };

一般情况下,如果使用 select new {..},在调用 updateChanges() 更新更改时会将其插入数据库吗? - Dany Khalife
@DanyKhalife 当您使用选择语句时,无需调用updateChanges。如果您这样做,它将不会插入任何内容,而只会在数据库中执行一个选择语句。 - daryal

1

这是一篇很棒的文章,讲述了从LINQ查询创建新对象所需的语法。

但是,如果用于填充对象字段的赋值不仅仅是简单的赋值,例如将字符串解析为整数,而且其中一个赋值失败了,就无法调试。您无法在任何单个赋值上创建断点。

如果您将所有赋值移动到子例程中,并从那里返回新对象,并尝试在该例程中设置断点,则可以在该例程中设置断点,但永远不会触发断点。

所以,不要使用以下方式:

var query2 = from c in doc.Descendants("SuggestionItem")
                select new SuggestionItem
                       { Phrase = c.Element("Phrase").Value
                         Blocked = bool.Parse(c.Element("Blocked").Value),
                         SeenCount = int.Parse(c.Element("SeenCount").Value)
                       };

或者

var query2 = from c in doc.Descendants("SuggestionItem")
                         select new SuggestionItem(c);

我相反地做了这个:

List<SuggestionItem> retList = new List<SuggestionItem>();

var query = from c in doc.Descendants("SuggestionItem") select c;

foreach (XElement item in query)
{
    SuggestionItem anItem = new SuggestionItem(item);
    retList.Add(anItem);
}

这使我能够轻松调试并找出哪个赋值操作失败了。在这种情况下,XElement缺少我正在解析以设置在SuggestionItem中的字段。
在编写新库例程的单元测试时,我遇到了Visual Studio 2017的这些陷阱。

这里的 SuggestionItem 是什么?它在你的回答中提到了,但是却找不到它的具体位置。 - Vinod Srivastav

1
如果您想要对每种类型执行查找并获取其频率,则需要将枚举转换为字典。
var types = new[] {typeof(string), typeof(string), typeof(int)};
var x = types
        .GroupBy(type => type)
        .ToDictionary(g => g.Key, g => g.Count());
foreach (var kvp in x) {
    Console.WriteLine("Type {0}, Count {1}", kvp.Key, kvp.Value);
}
Console.WriteLine("string has a count of {0}", x[typeof(string)]);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接