gpt4 book ai didi

c# - 将 List 转换为范围列表

转载 作者:行者123 更新时间:2023-12-04 12:49:41 30 4
gpt4 key购买 nike

我需要转换 list整数到范围列表。

我有一个 List<int>包含 8, 22, 41 .这些值是来自 1 的完整列表中的分节符47 .

我正在尝试获取包含起始行和结束行的范围列表。输出应该是

{(1,7),(8,21),(22,40),(41,47)}

我已尝试从 question调整解决方案但无法让它工作。

看起来应该很简单,但也许不是。

最佳答案

即使程序有效,在查询期间您应该改变局部变量的答案也是危险的;不要养成这个坏习惯。

解决问题的最简单方法是编写一个迭代器 block 。假设您有明显的 Pair<T>类型;在 C# 7 中,您可能会使用元组;调整它以使用元组是一个简单的练习:

static IEnumerable<Pair<int>> MakeIntervals(
/* this */ IEnumerable<int> dividers, /* You might want an extension method.*/
int start,
int end)
{
// Precondition: dividers is not null, but may be empty.
// Precondition: dividers is sorted.
// If that's not true in your world, order it here.
// Precondition: dividers contains no value equal to or less than start.
// Precondition: dividers contains no value equal to or greater than end.
// If it is possible for these preconditions to be violated then
// the problem is underspecified; say what you want to happen in those cases.
int currentStart = start;
for (int divider in dividers)
{
yield return new Pair<int>(currentStart, divider - 1);
currentStart = divider;
}
yield return new Pair<int>(currentStart, end);
}

这是解决这个问题的正确方法。如果你想变得有点傻,你可以使用 Zip .从两个有用的扩展方法开始:

static IEnumerable<T> Prepend<T>(this IEnumerable<T> items, T first)
{
yield return first;
foreach(T item in items) yield return item;
}
static IEnumerable<T> Append<T>(this IEnumerable<T> items, T last)
{
foreach(T item in items) yield return item;
yield return last;
}

现在我们有了:

static IEnumerable<Pair<int>> MakeIntervals(
IEnumerable<int> dividers,
int start,
int end)
{
var starts = dividers.Prepend(start);
// This is the sequence 1, 8, 22, 41
var ends = dividers.Select(d => d - 1).Append(end);
// This is the sequence 7, 21, 40, 47
var results = starts.Zip(ends, (s, e) => new Pair<int>(s, e));
// Zip them up: (1, 7), (8, 21), (22, 40), (41, 47)
return results;
}

但是与直接编写迭代器 block 相比,这似乎是不必要的巴洛克式。此外,这会迭代两次集合,这被许多人认为是不好的风格。

解决问题的一个可爱方法是推广第一个解决方案:

static IEnumerable<R> SelectPairs<T, R>(
this IEnumerable<T> items,
IEnumerable<T, T, R> selector
)
{
bool first = true;
T previous = default(T);
foreach(T item in items) {
if (first) {
previous = item;
first = false;
}
else
{
yield return selector(previous, item);
previous = item;
}
}
}

现在你的方法是:

static IEnumerable<Pair<int>> MakeIntervals(
IEnumerable<int> dividers,
int start,
int end)
{
return dividers
.Prepend(start)
.Append(end + 1)
.SelectPairs((s, e) => new Pair<int>(s, e - 1);
}

我很喜欢最后一张。也就是说,我们得到 8, 22, 41 ,我们构造1, 8, 22, 41, 48 ,然后我们从中挑选出对并构造 (1, 7), (8, 21),等等。

关于c# - 将 List<int> 转换为范围列表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52084106/

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