私は次の方法にかなり満足しています。それは列挙可能でソートされた互いに素な範囲のリストを取り、範囲内にないアイテムをスキップします。範囲がnullの場合、すべてのアイテムをウォークします。列挙可能な範囲と範囲のリストは両方とも大きい可能性があります。この方法を可能な限り高性能にする必要があります。
誰かがもっとエレガントなコードを思いつくことができますか?私は主にC#の実装に興味がありますが、誰かが3文字のAPL実装を持っているのであれば、それもすばらしいことです。
public static IEnumerable<T> WalkRanges<T>(IEnumerable<T> source, List<Pair<int, int>> ranges)
{
Debug.Assert(ranges == null || ranges.Count > 0);
int currentItem = 0;
Pair<int, int> currentRange = new Pair<int, int>();
int currentRangeIndex = -1;
bool betweenRanges = false;
if (ranges != null)
{
currentRange = ranges[0];
currentRangeIndex = 0;
betweenRanges = currentRange.First > 0;
}
foreach (T item in source)
{
if (ranges != null) {
if (betweenRanges) {
if (currentItem == currentRange.First)
betweenRanges = false;
else {
currentItem++;
continue;
}
}
}
yield return item;
if (ranges != null) {
if (currentItem == currentRange.Second) {
if (currentRangeIndex == ranges.Count - 1)
break; // We just visited the last item in the ranges
currentRangeIndex = currentRangeIndex + 1;
currentRange = ranges[currentRangeIndex];
betweenRanges = true;
}
}
currentItem++;
}
}