使用LINQ在列表的开始和结束之间交替
本文关键字:结束 之间 开始 LINQ 列表 使用 | 更新日期: 2023-09-27 17:54:11
假设我有一个列表{1,3,5,7,9,11}
我想使用像
这样的代码遍历列表foreach (int myInt in myIntList.OrderBy(...))
{
/// Do stuff
}
但是这里的顺序是1然后11然后3然后9然后5然后7。我怎么用等等来排序呢?
我的实际情况稍微复杂一些,for循环看起来像这样:
foreach (Tuple<string, int, int, int> im in iconMappings.OrderBy(i => i.Item4).ThenByDescending(i => i.Item3))
{
// Do stuff
}
因此,像上面一样排序它们之后,我需要得到交替的元素,所以理想情况下,我想要一个可以应用于此的答案。
这是您想要的顺序:
List<int> myIntList = new List<int>(new[] { 1, 3, 5, 7, 9, 11 });
var result = myIntList
.Select((v, i) => new { Value = v, Index = i })
.OrderBy(v => Math.Min(v.Index, Math.Abs((myIntList .Count - 1) - v.Index)))
.Select(v => v.Value);
foreach (var v in result)
{
Console.WriteLine(v.ToString());
}
给:
1
11
3
9
5
7
这应该能奏效:
IEnumerable<int> alternatingOrder = intList
.Select((i, index) => new
{
i,
Margin = index < intList.Count / 2 ? index : intList.Count - ++index
})
.OrderBy(x => x.Margin)
.Select(x => x.i);
排序遵循一个模式,这取决于项目,您的排序逻辑存在于匹配第一个和最后一个,匹配第二个和最后一个等等。=> 1, n, 2, n-1,…所以基本上你需要循环list =>
var myNewList = new List<...>();
foreach(int i = 0, i < myItems.Count, i++)
{
myNewList.add(myItems.First());
myNewList.add(myItems.Last());
myItems.Remove(myItems.First());
myItems.Remove(myItems.Last();
}
对于一组任何项目(不仅仅是int
),一个可重用的tic-tac方法可以是:
class Program
{
static void Main(string[] args)
{
var numbers = new[] {1, 3, 5, 7, 9, 11, 13};
foreach (var num in numbers.TicTac())
{
Console.WriteLine(num);
}
Console.Read();
}
}
static class Extensions
{
public static IEnumerable<T> TicTac<T>(this IEnumerable<T> source)
{
var count = source.Count();
var leftIterator = source.GetEnumerator();
var rightIterator = source.Reverse().GetEnumerator();
int returned = 0;
bool right = false;
while (returned < count)
{
if (right)
{
rightIterator.MoveNext();
yield return rightIterator.Current;
}
else
{
leftIterator.MoveNext();
yield return leftIterator.Current;
}
returned++;
right = !right;
}
}
}
在您的例子中,您要么假设数组已经排序,要么在调用。
然后您可以优化它以了解source
是什么,例如提供更好的实现,如果source
是T[]
,或IList<T>
或其他。
另一个选择是不使用OrderBy,而是使用自定义枚举器。(为了举例,我省略了边界检查和其他东西)
public IEnumerable<int> GetNext(List<int> data)
{
int leftIndex = 0;
int rightIndex = data.Count() -1;
while(leftIndex < rightIndex)
{
yield return data[leftIndex++];
yield return data[rightIndex--];
}
}
使用
foreach(var a in GetNext(list)){...}
这样做的好处是
1)你不改变原始数组
2)不创建数据副本在内存中(对于大数组可能是有害的)
你只是以某种特定的方式滚动你已有的数据