1

我不确定这是否可能。我的班级我有一个看起来像这样的列表:

class Person
{
 string Firstname
 string Lastname
 DateTime Timestamp
}

现在我想按FirstnameLastname创建组

  • 约翰·迪尔,3:12
  • 约翰·迪尔,6:34
  • 约翰·迪尔,11:12
  • 汤姆金,1:12
  • 汤姆金,3:49
  • 汤姆金,4:22
  • 马库斯·费尔特,11:23

此外,我想按它们的Timestamp对这些组进行排序,最后一个应该是第一个,而这些组应该留在列表视图中显示它们

  • Markus Fert(组页眉)
    11:23(内容元素)

  • 约翰鹿
    11:12
    6:34

  • 汤姆金
    4:22
    3:49

  • 约翰·鹿
    3:12

  • 汤姆金
    1:22

希望任何Linq天才可以帮助我解决问题:)谢谢!


非常感谢谢尔盖,工作就像一个魅力!

此外,我想为我的组键创建一个自定义类,以在我的 ListView 标题中显示不同的附加内容。(不仅是拼接在一起的字符串)

我想将我的查询分配给这样的 IEnumerable:

IEnumerable<IGrouping<Header, Person>> PersonGroups 

标头包含每个人中包含的一些其他属性(例如,每个人还有一个国家、年龄、...)。也许你也可以在那里帮助我?


再次感谢谢尔盖。通过实现实现 ICompareable 接口的 Header 类解决了我的问题。

IEnumerable<IGrouping<Header, Person>> PersonGroups

 public class Header: IComparable<Header>
 {
     public Header(string firstname, string lastname)
     {
        Firstname= firstname;
        Lastname = lastname;
     }

     public string Firstname{ get; set; }
     public string Lastname{ get; set; }

     public int CompareTo(Header that)
     {
       if (this.Firstname == that.Firstname&& this.Lastname == that.Lastname)
          return 0;
       else
           return -1;
     }
  }

我的查询现在看起来像这样:

PersonGroups= persons.OrderByDescending(p => p.Timestamp)
                .GroupConsecutive(p => new Header(p.Firstname, p.Lastname));
4

2 回答 2

1

实际上,您需要先按时间戳对结果进行排序。然后才将这个有序序列按连续的人分组:

var query = 
  people.OrderByDescending(p => p.Timestamp.TimeOfDay)
        .GroupConsecutive(p => String.Format("{0} {1}", p.Firstname, p.Lastname))
        .Select(g => new {
             Header = g.Key,
             Content = String.Join("\n", g.Select(p => p.Timestamp.TimeOfDay))
        });

您将需要GroupConsecutive实现,它基于提供的选择器的相同值(在您的情况下为全名)创建连续项目组。

对于您的示例输入结果是:

[
  {
    "Header": "Markus Fert",
    "Content": "11:23:00"
  },
  {
    "Header": "John Deer",
    "Content": "11:12:00\n06:34:00"
  },
  {
    "Header": "Tom Kin",
    "Content": "04:22:00\n03:49:00"
  },
  {
    "Header": "John Deer",
    "Content": "03:12:00"
  },
  {
    "Header": "Tom Kin",
    "Content": "01:12:00"
  }
]
于 2014-02-11T07:24:04.330 回答
0

这是一种使用内置链接运算符的方法Aggregate

首先,我需要通过降序时间戳对列表进行排序,然后创建了一个名称格式化函数。

var op = people
    .OrderByDescending(p => p.Timestamp)
    .ToArray();

Func<Person, string> toName = p =>
    String.Format("{0} {1}", p.Firstname, p.Lastname);

现在我可以构建查询:

var query =
    op
        .Skip(1)
        .Aggregate(new []
        {
            new
            {
                Name = toName(op.First()),
                Timestamps = new List<string>()
                {
                    op.First().Timestamp.ToShortTimeString(),
                },
            },
        }.ToList(), (a, p) =>
        {
            var name = toName(p);
            if (name == a.Last().Name)
            {
                a.Last().Timestamps.Add(p.Timestamp.ToShortTimeString());
            }
            else
            {
                a.Add(new
                {
                    Name = name,
                    Timestamps = new List<string>()
                    {
                        p.Timestamp.ToShortTimeString(),
                    },
                });
            }
            return a;
        });

我得到了这个结果:

结果

于 2014-02-11T08:14:00.273 回答