Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Take the first five elements and the last five elements from an array by one query using LINQ

Tags:

arrays

c#

linq

I have been recently asked by a co-worker: Is it possible just take the first five elements and the last five elements by one query from an array?

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

What I've tried:

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

Is it possible to just take the first five elements and the last five elements by one query?

like image 879
StepUp Avatar asked Jul 30 '15 08:07

StepUp


People also ask

How do you print the first and last elements of an array?

To get the first and last elements of an array, access the array at index 0 and the last index. For example, arr[0] returns the first element, whereas arr[arr. length - 1] returns the last element of the array. Copied!

How do you use take and skip in Linq?

The Take operator is used to return a given number of rows from a database table and the Skip operator skips over a specifed number of rows in a database table. I create a data context class that has tables or a stored procedure.


5 Answers

You can use a .Where method with lambda that accepts the element index as its second parameter:

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

Output:

0, 1, 2, 3, 4, 14, 15, 16, 17, 18
like image 87
Fabjan Avatar answered Sep 20 '22 06:09

Fabjan


In case you are not playing code puzzles with your co-workers, but just want to create a new array with your criteria, I wouldn't do this with queries at all, but use Array.copy.

There are three distinct cases to consider:

  • the source array has fewer than 5 items
  • the source array has 5 to 9 items
  • the source array has 10 or more items

The third one is the simple case, as the first and last 5 elements are distinct and well defined.

The other two require more thought. I'm going to assume you want the following, check those assumptions:

If the source array has fewer than 5 items, you will want to have an array of 2 * (array length) items, for example [1, 2, 3] becomes [1, 2, 3, 1, 2, 3]

If the source array has between 5 and 9 items, you will want to have an array of exactly 10 items, for example [1, 2, 3, 4, 5, 6] becomes [1, 2, 3, 4, 5, 2, 3, 4, 5, 6]

A demonstration program is

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

which runs in O(1);

If you are playing code puzzles with your co-workers, well all the fun is in the puzzle, isn't it?

It's trivial though.

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

this runs in O(n).

like image 24
Martijn Avatar answered Sep 20 '22 06:09

Martijn


A solution with ArraySegment<> (requires .NET 4.5 (2012) or later):

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

And a solution with Enumerable.Range:

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

Both these solution avoid iterating through the "middle" of the array (indices 5 through 13).

like image 32
Jeppe Stig Nielsen Avatar answered Sep 21 '22 06:09

Jeppe Stig Nielsen


Try this:

var result = someArray.Where((a, i) => i < 5 || i >= someArray.Length - 5);
like image 32
Amit Tiwari Avatar answered Sep 22 '22 06:09

Amit Tiwari


This should work

someArray.Take(5).Concat(someArray.Skip(someArray.Count() - 5)).Take(5);
like image 22
Sandeep Avatar answered Sep 19 '22 06:09

Sandeep