使用LINQ通过一个查询获取数组中的前五个元素和最后五个元素

Ste*_*pUp 20 c# linq arrays

我最近被一位同事问到:是否可以通过一个数组中的一个查询获取前五个元素和最后五个元素?

int[] someArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
Run Code Online (Sandbox Code Playgroud)

我尝试过的:

int[] someArray = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };
var firstFiveResults = someArray.Take(5);
var lastFiveResults = someArray.Skip(someArray.Count() - 5).Take(5);
var result = firstFiveResults;
result = result.Concat(lastFiveResults);
Run Code Online (Sandbox Code Playgroud)

是否可以通过一个查询获取前五个元素和后五个元素?

Fab*_*jan 28

您可以使用.Wherelambda接受元素索引作为其第二个参数的方法:

int[] someArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18 };

int[] newArray = someArray.Where((e, i) => i < 5 || i >= someArray.Length - 5).ToArray();

foreach (var item in newArray) 
{
    Console.WriteLine(item);
}
Run Code Online (Sandbox Code Playgroud)

输出:

0, 1, 2, 3, 4, 14, 15, 16, 17, 18
Run Code Online (Sandbox Code Playgroud)

  • 如果输入序列少于5个项目,这个答案是唯一没有抛出的答案.然而,OP从未指定过这种情况的行为 - 即重叠的头部和尾部是否应该在输出中重复? (3认同)
  • 只是一个编码的东西,但我更喜欢`(_,i)=> i <5 || i> = someArray.Length - 5`.`_`表示未使用该变量.`> =`允许`5`对应于从列表末尾获取的元素数. (2认同)

Jep*_*sen 11

ArraySegment<>(需要.NET 4.5(2012)或更高版本)的解决方案:

var result = new ArraySegment<int>(someArray, 0, 5)
  .Concat(new ArraySegment<int>(someArray, someArray.Length - 5, 5));
Run Code Online (Sandbox Code Playgroud)

并提供以下解决方案Enumerable.Range:

var result = Enumerable.Range(0, 5).Concat(Enumerable.Range(someArray.Length - 5, 5))
  .Select(idx => someArray[idx]);
Run Code Online (Sandbox Code Playgroud)

这两种解决方案都避免迭代遍历数组的"中间"(索引5到13).


Mar*_*ijn 6

如果你没有和你的同事一起玩代码谜题,但只是想用你的标准创建一个新的数组,我根本不会用查询来做这个,而是使用Array.copy.

有三种不同的案例需要考虑:

  • 源数组少于5个项目
  • 源数组有5到9个项目
  • 源数组有10个或更多项

第三个是简单的情况,因为第一个和后五个元素是不同的并且定义明确.

另外两个需要更多思考.我假设您需要以下内容,请检查以下假设:

如果源数组少于5个项目,您将需要一个2*(数组长度)项目的数组,例如[1,2,3]变为[1,2,3,1,2,3]

如果源数组有5到9个项目,你将需要一个恰好有10个项目的数组,例如[1,2,3,4,5,6]变为[1,2,3,4,5] 2,3,4,5,6]

示范项目是

public static void Main()
{
    Console.WriteLine(String.Join(", ", headandtail(new int[]{1, 2, 3})));
    Console.WriteLine(String.Join(", ", headandtail(new int[]{1, 2, 3, 4, 5, 6})));
    Console.WriteLine(String.Join(", ", headandtail(new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11})));
}

private static T[] headandtail<T>(T[] src) {
    int runlen = Math.Min(src.Length, 5);
    T[] result = new T[2 * runlen];
    Array.Copy(src, 0, result, 0, runlen);
    Array.Copy(src, src.Length - runlen, result, result.Length - runlen, runlen);
    return result;
}
Run Code Online (Sandbox Code Playgroud)

在O(1)中运行;

如果你正在玩的代码谜题你的同事,以及所有的乐趣是难题,不是吗?

虽然这很微不足道.

src.Take(5).Concat(src.Reverse().Take(5).Reverse()).ToArray();
Run Code Online (Sandbox Code Playgroud)

这在O(n)中运行.