2

我正在尝试按某个字段对对象列表进行分组。

稍后,我需要按如下方式使用此列表:

for(i=0; i< list.Count; i++)
{
   if(i == 0)
    continue;

   if (list[i].property != list[i-1].property)
   dosomething;
}

我需要做一个 for 循环,这样我就可以说“如果在这个之前的项目的属性不同......

当我尝试订购列表时,问题就来了。如果我使用 list.GroupBy,我将无法访问列表项的成员。如果我使用 list.OrderBy,我必须将其设置为 ienumerable,因此不能使用 for 循环,因为 ienumerables 不适用于列表索引。

有没有办法在 foreach 循环中实现这个功能(不引用索引)?如果没有,是否有另一种方式来订购不需要将其设置为可枚举的列表?

4

3 回答 3

3

四个选项:

  • 使用OrderByand thenToList获取排序列表。然后您可以使用现有代码,尽管我建议从 1 开始循环,而不是从 0 开始并在第一次迭代中立即中断。
  • 使用OrderBy然后Zip

    var ordered = input.OrderBy(...);
    var zipped = ordered.Zip(ordered.Skip(1),
                             (Previous, Current) => new { Previous, Current });
    
    foreach (var pair in zipped)
    {
        if (pair.Previous.Property == pair.Current.Property)
        {
            ... Whatever you want to do
        }
    }
    

    请注意,不幸的是,这将对输入进行两次排序。没有避免这种情况的内置方法(无需调用ToList或其他)。诚然,编写“自压缩”扩展方法不会太难。

  • 使用OrderBy并保留“先前的属性”:

    var ordered = input.OrderBy(...);
    // This is like using foreach, but with a simple way to get the
    // first item
    using (var iterator = ordered.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            return; // Or whatever. No items!
        }
        var previousProperty = iterator.Current.Property;
        while (iterator.MoveNext())
        {
            var currentProperty = iterator.Current.Property;
            if (previousProperty == currentProperty)
            {
                ... Whatever you want to do
            }
            previousProperty = currentProperty;
        }
    }
    
  • 使用List<T>.Sort

于 2012-09-21T20:08:34.010 回答
0

这只是 Skeet 中一个选项的重复。把支票给他。

ForEach 不需要索引。无法使用 ForEach 从列表中删除项目。

class Program
{
    static void Main(string[] args)
    {
        List<SortMe> SortMes = new List<SortMe>();

        SortMes.Add(new SortMe("aaa"));
        SortMes.Add(new SortMe("bbb"));
        SortMes.Add(new SortMe("ccc"));
        SortMes.Add(new SortMe("aaa"));
        SortMes.Add(new SortMe("bbb"));
        SortMes.Add(new SortMe("ccc"));
        SortMes.Add(new SortMe("ccc"));
        SortMes.Add(new SortMe("bbb"));
        SortMes.Add(new SortMe("aaa"));
        SortMes.Add(new SortMe("ccc"));
        SortMes.Add(new SortMe("bbb"));
        SortMes.Add(new SortMe("aaa"));

        SortMe SortMeLast = null;

        foreach (SortMe SortMeCurrent in SortMes.OrderBy(x => x.Name))
        {
            Console.WriteLine("   Current     " + SortMeCurrent.Name);
            if (SortMeLast != null)
            {
                if (SortMeCurrent.Name != SortMeLast.Name)
                {
                    // do something
                    Console.WriteLine("Do Something");
                }
            }
            SortMeLast = SortMeCurrent;
        }
        Console.ReadLine();
    }
}
public class SortMe
{
    public string Name { get; set; }
    public SortMe(string name) { Name = name; } 
}
于 2012-09-21T20:49:46.410 回答
0

myitem previous您可以在循环之前定义一个(其中myitem列表中的类型相同),然后在每个列表的末尾,设置previous为当前项目。如果你这样做,请确保检查previousnull 因为它第一次没有值。

于 2012-09-21T20:08:38.593 回答