gpt4 book ai didi

c# - 分组连续相同的项目 : IEnumerable to IEnumerable>

转载 作者:太空狗 更新时间:2023-10-29 20:06:19 26 4
gpt4 key购买 nike

我有一个有趣的问题:给定一个 IEnumerable<string> , 是否有可能产生 IEnumerable<IEnumerable<string>> 的序列一次将相同的相邻字符串分组?

让我解释一下。

<强>1。基本说明示例:

考虑以下 IEnumerable<string> (伪表示):

{"a","b","b","b","c","c","d"}

如何获得 IEnumerable<IEnumerable<string>>这将产生某种形式的东西:

{ // IEnumerable<IEnumerable<string>>
{"a"}, // IEnumerable<string>
{"b","b","b"}, // IEnumerable<string>
{"c","c"}, // IEnumerable<string>
{"d"} // IEnumerable<string>
}

方法原型(prototype)为:

public IEnumerable<IEnumerable<string>> Group(IEnumerable<string> items)
{
// todo
}

但也可以是:

public void Group(IEnumerable<string> items, Action<IEnumerable<string>> action)
{
// todo
}

...哪里action将为每个子序列调用。

<强>2。更复杂的样本

好的,第一个示例非常简单,只是为了让高层意图清晰。

现在假设我们正在处理 IEnumerable<Anything> , 其中Anything是这样定义的类型:

public class Anything
{
public string Key {get;set;}
public double Value {get;set;}
}

我们现在要根据键生成子序列(将具有相同键的每个连续 Anything 分组)以便稍后使用它们以按组计算总值:

public void Compute(IEnumerable<Anything> items)
{
Console.WriteLine(items.Sum(i=>i.Value));
}

// then somewhere, assuming the Group method
// that returns an IEnumerable<IEnumerable<Anything>> actually exists:
foreach(var subsequence in Group(allItems))
{
Compute(subsequence);
}

<强>3。重要提示

  • 仅对原始序列一次迭代
  • 没有中间集合分配(我们可以假设原始序列中有数百万个项目,每个组中有数百万个连续项目)
  • 保留枚举器和延迟执行行为
  • 我们可以假设结果子序列只会迭代一次,并且会按顺序迭代。

可以吗,怎么写?

最佳答案

这是您要找的吗?

  • 只迭代列表一次。
  • 推迟执行。
  • 没有中间集合(我的另一篇文章不符合这个标准)。

此解决方案依赖于对象状态,因为很难在使用 yield(无 ref 或 out 参数)的两个 IEnumerable 方法之间共享状态。

internal class Program
{
static void Main(string[] args)
{
var result = new[] { "a", "b", "b", "b", "c", "c", "d" }.Partition();
foreach (var r in result)
{
Console.WriteLine("Group".PadRight(16, '='));
foreach (var s in r)
Console.WriteLine(s);
}
}
}

internal static class PartitionExtension
{
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> src)
{
var grouper = new DuplicateGrouper<T>();
return grouper.GroupByDuplicate(src);
}
}

internal class DuplicateGrouper<T>
{
T CurrentKey;
IEnumerator<T> Itr;
bool More;

public IEnumerable<IEnumerable<T>> GroupByDuplicate(IEnumerable<T> src)
{
using(Itr = src.GetEnumerator())
{
More = Itr.MoveNext();

while (More)
yield return GetDuplicates();
}
}

IEnumerable<T> GetDuplicates()
{
CurrentKey = Itr.Current;
while (More && CurrentKey.Equals(Itr.Current))
{
yield return Itr.Current;
More = Itr.MoveNext();
}
}
}

编辑:添加了更清洁的扩展方法。修复了循环测试逻辑,以便首先评估“更多”。

编辑:完成后处理枚举器

关于c# - 分组连续相同的项目 : IEnumerable<T> to IEnumerable<IEnumerable<T>>,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2828203/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com