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

时间:2015-07-30 08:19:37

标签: c# arrays linq

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

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

我尝试过的事情:

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);

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

7 个答案:

答案 0 :(得分:28)

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

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);
}

输出:

0, 1, 2, 3, 4, 14, 15, 16, 17, 18

答案 1 :(得分:11)

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

var result = new ArraySegment<int>(someArray, 0, 5)
  .Concat(new ArraySegment<int>(someArray, someArray.Length - 5, 5));

使用Enumerable.Range的解决方案:

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

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

答案 2 :(得分: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;
}

在O(1)中运行;

如果你与你的同事一起玩代码谜题,那么所有的乐趣都在谜题中,不是吗?

虽然这很简单。

src.Take(5).Concat(src.Reverse().Take(5).Reverse()).ToArray();

这在O(n)中运行。

答案 3 :(得分:4)

试试这个:

var result = someArray.Where((a, i) => i < 5 || i >= someArray.Length - 5);

答案 4 :(得分:2)

这应该有效

someArray.Take(5).Concat(someArray.Skip(someArray.Count() - 5)).Take(5);

答案 5 :(得分:2)

试试这个:

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.Reverse().Take(5).Reverse();
var result = firstFiveResults;
result = result.Concat(lastFiveResults);

第二个反向()重新排序数字,这样你就不会得到18,17,16,15,14

答案 6 :(得分:1)

请试试这个:

import re
p = re.compile(r'\[{2}(?:[^|\]]*\|)?([^]]*)]{2}')
test_str = "He lives in [[Gimhae city|Gimhae]]. He lives in [[Gimhae]]. "
result = re.sub(p, r"\1", test_str)
print(result) # => He lives in Gimhae. He lives in Gimhae.