Related
I have some problems. I have 2 list such as:
List<int> firstList = new List<int> { 1, 2, 2, 3, 5};
List<int> secondList = new List<int> { 2, 3, 1 };
⇒ True result is: {1, 3, 0}
I would like to get the first index of numbers in secondList that exists in firstList. I used list.BinarySearch() but the result was {2, 3, 0}.
List<int> firstList = new List<int> { 1, 2, 2, 3, 5};
List<int> secondList = new List<int> { 2, 3, 1 };
var output = secondList.Select(item => firstList.IndexOf(item)); // [1 , 3 , 0]
You can replace the IndexOf with a BinarySearch logic, but BinarySearch returns the first matched element index, so you won't get the lowest number, IndexOf does return the lowest matching index.
The problem is that when the list contains duplicate values as in your case, the BinarySearch method will return the index of any of the matching values (non deterministic).
To get the desired result, you could create and use a custom extension method like this:
public static class ListExtensions
{
public static int BinarySearchFirst<T>(this List<T> source, T item, IComparer<T> comparer = null)
{
if (comparer == null) comparer = Comparer<T>.Default;
int index = source.BinarySearch(item, comparer);
while (index > 0 && comparer.Compare(source[index], source[index - 1]) == 0)
index--;
return index;
}
}
Sample usage:
var result = secondList.Select(x => firstList.BinarySearchFirst(x)).ToList();
// { 1, 3, 0 }
C++ has a standard library function for this called lower_bound().
Here's a C# implementation. This is useful if you are searching large collections:
public static int LowerBound<T>(IList<T> values, T target, int first, int last)
where T : IComparable<T>
{
int left = first;
int right = last;
while (left < right)
{
int mid = left + (right - left) / 2;
var middle = values[mid];
if (middle.CompareTo(target) < 0)
left = mid + 1;
else
right = mid;
}
return left;
}
That doesn't return -1 for elements that it doesn't find, so to fix that we can wrap it like so:
public static int LowerBoundOrMinusOne<T>(IList<T> values, T target, int first, int last)
where T : IComparable<T>
{
int result = LowerBound(values, target, first, last);
if (result >= last || result < first || values[result].CompareTo(target) != 0)
return -1;
return result;
}
Here is how you use it:
List<int> firstList = new List<int> { 1, 2, 2, 3, 5 };
List<int> secondList = new List<int> { 2, 3, 1 };
List<int> result = secondList
.Select(value => LowerBoundOrMinusOne(firstList, value, 0, firstList.Count))
.ToList();
Console.WriteLine(string.Join(", ", result));
Of course, this is mainly of benefit to large lists because it has an O(Log2(N)) rather than an O(N) complexity.
Iterate through second array and get index of element in first array:
foreach (int item in secondList)
{
Console.WriteLine(firstList.IndexOf(item));
}
If you have a large firstList and so you have to use BinarySearch try amending it: find out the item (which is not guaranteed to be the leftmost one) by BinarySearch, then move to the left while having read the same item:
List<int> firstList = new List<int> { 1, 2, 2, 3, 5 };
List<int> secondList = new List<int> { 2, 3, 1, 123 };
var result = secondList
.Select(item => firstList.BinarySearch(item))
.Select(index => index < 0 ? -1 : Enumerable
.Range(0, index + 1) // we have to scan [0..index] at the worst case
.Select(i => index - i) // scan in reverse
.TakeWhile(i => firstList[index] == firstList[i]) // take while items are the same
.Last()); // finally, we want the last item
Test
// 1, 3, 0, -1
Console.Write(String.Join(", ", result));
I have a list of lists of int <List<List<int>> which represents a directional vector
for instance
(1,2)
(1,3)
(2,4)
(3,5)
(4,3)
(5,1)
and I want to create all possible routes with those vectors so that the final route doesn't create an endless circle (ends on itself)
so:
(1,2)
(1,3)
(2,4)
(3,5)
(4,3)
(5,1)
(1,2,4)
(1,2,4,3)
(1,2,4,3,5)
(1,2,4,3,5,1)
(1,3,5)
(1,3,5,1)
(2,4,3)
(2,4,3,5)
(2,4,3,5,1)
(2,4,3,5,1,2)
(3,5,1)
etc...
I haven't found an efficient method of doing such a thing.
I have previous tried creating all possible combinations using
private IEnumerable<int> constructSetFromBits(int i)
{
for (int n = 0; i != 0; i /= 2, n++)
{
if ((i & 1) != 0)
yield return n;
}
}
public IEnumerable<List<T>> ProduceWithRecursion(List<T> allValues)
{
for (var i = 0; i < (1 << allValues.Count); i++)
{
yield return ConstructSetFromBits(i).Select(n => allValues[n]).ToList();
}
}
which worked well but ignored the direction aspect of the problem.
The method doesn't have to be recursive although I suspect that might be the most sensible way to go about it
Looks like breadth first search:
private static IEnumerable<List<int>> BreadthFirstSearch(IEnumerable<List<int>> source) {
List<List<int>> frontier = source
.Select(item => item.ToList())
.ToList();
while (frontier.Any()) {
for (int i = frontier.Count - 1; i >= 0; --i) {
List<int> path = frontier[i];
yield return path;
frontier.RemoveAt(i);
// prevent loops
if (path.IndexOf(path[path.Count - 1]) < path.Count - 1)
continue;
int lastVertex = path[path.Count - 1];
var NextVertexes = source
.Where(edge => edge[0] == lastVertex)
.Select(edge => edge[1])
.Distinct();
foreach (var nextVertex in NextVertexes) {
var nextPath = path.ToList();
nextPath.Add(nextVertex);
frontier.Add(nextPath);
}
}
}
}
Test
List<List<int>> list = new List<List<int>>() {
new List<int>() {1, 2},
new List<int>() {1, 3},
new List<int>() {2, 4},
new List<int>() {3, 5},
new List<int>() {4, 3},
new List<int>() {5, 1},
};
var result = BreadthFirstSearch(list)
.Select(way => string.Format("({0})", string.Join(",", way)));
Console.Write(string.Join(Environment.NewLine, result));
Result:
(5,1)
(4,3)
(3,5)
(2,4)
(1,3)
(1,2)
(1,2,4)
(1,3,5)
(2,4,3)
(3,5,1)
(4,3,5)
(5,1,3)
(5,1,2)
(5,1,2,4)
(5,1,3,5)
(4,3,5,1)
(3,5,1,3)
(3,5,1,2)
(2,4,3,5)
(1,3,5,1)
(1,2,4,3)
(1,2,4,3,5)
(2,4,3,5,1)
(3,5,1,2,4)
(4,3,5,1,3)
(4,3,5,1,2)
(5,1,2,4,3)
(5,1,2,4,3,5)
(4,3,5,1,2,4)
(3,5,1,2,4,3)
(2,4,3,5,1,3)
(2,4,3,5,1,2)
(1,2,4,3,5,1)
I'm asking this question again, since the last time I asked it, it was falsely marked as duplicated. I am going to include some more information this time, that might make it easier to understand my need (it may very well have been my own fault for not defining the question properly).
I'm trying to split a list of a generic type into 4 lists. For simplicity and understanding, I will use a list of integers in this example, but that shouldn't make a difference.
I have done a lot of searching, found multiple answers like "Split List into Sublists with LINQ", using batch methods to split, I have tried MoreLinq's Batch methods and so on. Those suggestions work fine for what they should, but they do not work the way I need them to.
If I have a list containing the following elements (integers ranging 1-25):
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25]
Then what I need to do is make 4 lists with a variable number of elements in them, where the elements increment in the same list, instead of jumping to the next list with the next element.
[ 1, 2, 3, 4, 5, 6, 7]
[ 8, 9, 10, 11, 12, 13, 14]
[15, 16, 17, 18, 19, 20, 21]
[20, 21, 22, 23, 24, 25]
When using the solutions in either of the questions linked, with 4 "parts" as the parameter, I get lists like this (this is the example where the element jumps to the next list instead of just the next element of the list):
[1, 5, 9, 13, 17, 21, 25],
[2, 6, 10, 14, 18, 22, 26],
[3, 7, 11, 15, 19, 23, 27],
[4, 8, 12, 16, 20, 24]
or this (does the same as MoreLinq's Batch method)
[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12],
[13, 14, 15, 16],
[17, 18, 19, 20],
[21, 22, 23, 24],
[25, 26, 27],
So the first solution splits the list into 4 lists, but puts the elements in the wrong order. The second solution splits the lists in the right order, but not in the right length. In the last solution, he gets X amount of lists with 4 elements in each, where I need to have 4 lists with X elements in each.
You can use following extension method to split list on required number of sub-lists, and include additional items in first sub-list:
public static IEnumerable<List<T>> Split<T>(this List<T> source, int count)
{
int rangeSize = source.Count / count;
int firstRangeSize = rangeSize + source.Count % count;
int index = 0;
yield return source.GetRange(index, firstRangeSize);
index += firstRangeSize;
while (index < source.Count)
{
yield return source.GetRange(index, rangeSize);
index += rangeSize;
}
}
With given input
var list = Enumerable.Range(1, 25).ToList();
var result = list.Split(4);
Result is
[
[ 1, 2, 3, 4, 5, 6, 7 ],
[ 8, 9, 10, 11, 12, 13 ],
[ 14, 15, 16, 17, 18, 19 ],
[ 20, 21, 22, 23, 24, 25 ]
]
UPDATE: This solution adds additional item to each range
public static IEnumerable<List<T>> Split<T>(this List<T> source, int count)
{
int rangeSize = source.Count / count;
int additionalItems = source.Count % count;
int index = 0;
while (index < source.Count)
{
int currentRangeSize = rangeSize + ((additionalItems > 0) ? 1 : 0);
yield return source.GetRange(index, currentRangeSize);
index += currentRangeSize;
additionalItems--;
}
}
Here is another solution based on IEnumerable<T>. It has the following characteristics:
Always yields batchCount items, if the source enumerable is smaller than the batch size, it will yield empty lists.
Favors larger lists at the front (e.g. when the batchCount is 2 and the size is 3, the length of the results will be [2,1].
Iterates multiple times of the IEnumerable. This means AsEnumerable should be called somewhere if something like an Entity Framework query is executed here.
The first example is optimized for List<T>
public static class BatchOperations
{
public static IEnumerable<List<T>> Batch<T>(this List<T> items, int batchCount)
{
int totalSize = items.Count;
int remain = totalSize % batchCount;
int skip = 0;
for (int i = 0; i < batchCount; i++)
{
int size = totalSize / batchCount + (i <= remain ? 1 : 0);
if (skip + size > items.Count) yield return new List<T>(0);
else yield return items.GetRange(skip, size);
skip += size;
}
}
public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> items, int batchCount)
{
int totalSize = items.Count();
int remain = totalSize%batchCount;
int skip = 0;
for (int i = 0; i < batchCount; i++)
{
int size = totalSize/batchCount + (i <= remain ? 1 : 0);
yield return items.Skip(skip).Take(size);
skip += size;
}
}
}
Sergey's answer is clearly the best for this, but for completeness here's a solution you could use if you did not want to make copies of the sublists for some reason (perhaps because you just had IEnumerable<T> as input):
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp1
{
public static class EnumerableExt
{
public static IEnumerable<IEnumerable<T>> Partition<T>(this IEnumerable<T> input, int blockCount, int count)
{
int blockSize = count/blockCount;
int currentBlockSize = blockSize + count%blockSize;
var enumerator = input.GetEnumerator();
while (enumerator.MoveNext())
{
yield return nextPartition(enumerator, currentBlockSize);
currentBlockSize = blockSize;
}
}
private static IEnumerable<T> nextPartition<T>(IEnumerator<T> enumerator, int blockSize)
{
do
{
yield return enumerator.Current;
}
while (--blockSize > 0 && enumerator.MoveNext());
}
}
class Program
{
private void run()
{
var list = Enumerable.Range(1, 25).ToList();
var sublists = list.Partition(4, list.Count);
foreach (var sublist in sublists)
Console.WriteLine(string.Join(" ", sublist.Select(element => element.ToString())));
}
static void Main()
{
new Program().run();
}
}
}
I guess this would run much more slowly than using Lists, but it would use much less memory.
const int groupSize = 4;
var items = new []{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25};
var currentGroupIndex=-1;
var step1 = items.Select(a =>{
if (++currentGroupIndex >= groupSize)
currentGroupIndex = 0;
return new {Group = currentGroupIndex, Value = a};
}).ToArray();
var step2 = step1.GroupBy(a => a.Group).Select(a => a.ToArray()).ToArray();
var group1 = step2[0].Select(a => a.Value).ToArray();
var group2 = step2[1].Select(a => a.Value).ToArray();
var group3 = step2[2].Select(a => a.Value).ToArray();
var group4 = step2[3].Select(a => a.Value).ToArray();
What this does is it first introduces an counter (currentGroupIndex) which starts at zero and will be incremented for each element in the list. The index gets reset to zero when the group size has reached.
the variable step1 now contains items continaing a Group and a Value property.
The Group value is then used in the GroupBy statement.
Take & Skip could be very helpful here i think but personally i like using Func to make these choices, makes the method more flexible.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Splitter
{
class Program
{
static void Main(string[] args)
{
List<int> numbers = Enumerable.Range(1, 25).ToList();
int groupCount = 4;
var lists = numbers.Groupem(groupCount, (e, i) =>
{
// In what group do i wanna have this element.
int divider = numbers.Count / groupCount;
int overflow = numbers.Count % divider;
int index = (i - overflow) / divider;
return index < 0 ? 0 : index;
});
Console.WriteLine("numbers: {0}", numbers.ShowContent());
Console.WriteLine("Parts");
foreach (IEnumerable<int> list in lists)
{
Console.WriteLine("{0}", list.ShowContent());
}
}
}
public static class EnumerableExtensions
{
private static List<T>[] CreateGroups<T>(int size)
{
List<T>[] groups = new List<T>[size];
for (int i = 0; i < groups.Length; i++)
{
groups[i] = new List<T>();
}
return groups;
}
public static void Each<T>(this IEnumerable<T> source, Action<T, int> action)
{
var i = 0;
foreach (var e in source) action(e, i++);
}
public static IEnumerable<IEnumerable<T>> Groupem<T>(this IEnumerable<T> source, int groupCount, Func<T, int, int> groupPicker, bool failOnOutOfBounds = true)
{
if (groupCount <= 0) throw new ArgumentOutOfRangeException("groupCount", "groupCount must be a integer greater than zero.");
List<T>[] groups = CreateGroups<T>(groupCount);
source.Each((element, index) =>
{
int groupIndex = groupPicker(element, index);
if (groupIndex < 0 || groupIndex >= groups.Length)
{
// When allowing some elements to fall out, set failOnOutOfBounds to false
if (failOnOutOfBounds)
{
throw new Exception("Some better exception than this");
}
}
else
{
groups[groupIndex].Add(element);
}
});
return groups;
}
public static string ShowContent<T>(this IEnumerable<T> list)
{
return "[" + string.Join(", ", list) + "]";
}
}
}
How about this, includes parameter checking, works with an emtpy set.
Completes in two passes, should be fast, I haven't tested.
public static IList<Ilist<T>> Segment<T>(
this IEnumerable<T> source,
int segments)
{
if (segments < 1)
{
throw new ArgumentOutOfRangeException("segments");
}
var list = source.ToList();
var result = new IList<T>[segments];
// In case the source is empty.
if (!list.Any())
{
for (var i = 0; i < segments; i++)
{
result[i] = new T[0];
}
return result;
}
int remainder;
var segmentSize = Math.DivRem(list.Count, segments, out remainder);
var postion = 0;
var segment = 0;
while (segment < segments)
{
var count = segmentSize;
if (remainder > 0)
{
remainder--;
count++;
}
result[segment] = list.GetRange(position, count);
segment++;
position += count;
}
return result;
}
Here is an optimized and lightweight O(N) extension method solution
public static void Bifurcate<T>(this IEnumerable<T> _list, int amountOfListsOutputted, IList<IList<T>> outLists)
{
var list = _list;
var index = 0;
outLists = new List<IList<T>>(amountOfListsOutputted);
for (int i = 0; i < amountOfListsOutputted; i++)
{
outLists.Add(new List<T>());
}
foreach (var item in list)
{
outLists[index % amountOfListsOutputted].Add(item);
++index;
}
}
Simply use it like this:
public static void Main()
{
var list = new List<int>(1000);
//Split into 2
list.Bifurcate(2, out var twoLists);
var splitOne = twoLists[0];
var splitTwo = twoLists[1];
// splitOne.Count == 500
// splitTwo.Count == 500
//Split into 3
list.Bifurcate(3, out var threeLists);
var _splitOne = twoLists[0];
var _splitTwo = twoLists[1];
var _splitThree = twoLists[2];
// _splitOne.Count == 334
// _splitTwo.Count = 333
// _splitThree.Count == 333
}
I'm looking for a way to prevent repeating items in a list but still preserve the order.
For example
1, 2, 3, 4, 4, 4, 1, 1, 2, 3, 4, 4
should become
1, 2, 3, 4, 1, 2, 3, 4
I've done it quite inelegantly using a for loop, checking the next item as follows
public static List<T> RemoveSequencialRepeats<T>(List<T> input)
{
var result = new List<T>();
for (int index = 0; index < input.Count; index++)
{
if (index == input.Count - 1)
{
result.Add(input[index]);
}
else if (!input[index].Equals(input[index + 1]))
{
result.Add(input[index]);
}
}
return result;
}
Is there a more elegant way to do this, preferably with LINQ?
You can create extension method:
public static IEnumerable<T> RemoveSequentialRepeats<T>(
this IEnumerable<T> source)
{
using (var iterator = source.GetEnumerator())
{
var comparer = EqualityComparer<T>.Default;
if (!iterator.MoveNext())
yield break;
var current = iterator.Current;
yield return current;
while (iterator.MoveNext())
{
if (comparer.Equals(iterator.Current, current))
continue;
current = iterator.Current;
yield return current;
}
}
}
Usage:
var result = items.RemoveSequentialRepeats().ToList();
You can also use pure LINQ:
List<int> list = new List<int>{1, 2, 3, 4, 4, 4, 1, 1, 2, 3, 4, 4};
var result = list.Where((x, i) => i == 0 || x != list[i - 1]);
If you really really hate the world, pure LINQ:
var nmbs = new int[] { 1, 2, 3, 4, 4, 4, 1, 1, 2, 3, 4, 4, 5 };
var res = nmbs
.Take(1)
.Concat(
nmbs.Skip(1)
.Zip(nmbs, (p, q) => new { prev = q, curr = p })
.Where(p => p.prev != p.curr)
.Select(p => p.curr));
But note that you'll need to enumerate (at least partially) the enumerable 3 times (the Take, the "left" part of Zip, the first parameters of Zip). This method is slower than building a yield method or doing it directly.
Explanation:
You take the first number (.Take(1))
You take all the numbers from the second (.Skip(1)) and pair it with all the numbers (.Zip(nmbs). We will call curr the numbers from the first "collection" and prev the numbers from the second "collection" ((p, q) => new { prev = q, curr = p })). You then take only the numbers that are different from the previous number (.Where(p => p.prev != p.curr)) and from these you take the curr value and discard the prev value (.Select(p => p.curr))
You concat these two collections (.Concat()
you could write simple LINQ :
var l = new int[] { 1, 2, 3, 4, 4, 4, 1, 1, 2, 3, 4, 4 };
var k = new Nullable<int>();
var nl = l.Where(x => { var res = x != k; k = x; return res; }).ToArray();
int[8] { 1, 2, 3, 4, 1, 2, 3, 4 }
or pythonic (well, my best try) way:
l.Zip(l.Skip(1), (x, y) => new[] { x, y })
.Where(z => z[0] != z[1]).Select(a => a[0])
.Concat(new[] { l[l.Length - 1] }).ToArray()
int[8] { 1, 2, 3, 4, 1, 2, 3, 4 }
the simplest one (edit: haven't seen that it already suggested by King King)
l.Where((x, i) => i == l.Length - 1 || x != l[i + 1]).ToArray()
int[8] { 1, 2, 3, 4, 1, 2, 3, 4 }
If you want LINQ statement that do not rely on captured value of result inside the call you'll need some construct with aggregate as it is the only method that carries value along with operation. I.e. based on Zaheer Ahmed's code:
array.Aggregate(new List<string>(),
(items, element) =>
{
if (items.Count == 0 || items.Last() != element)
{
items.Add(element);
}
return items;
});
Or you can even try to build list without if:
array.Aggregate(Enumerable.Empty<string>(),
(items, element) => items.Concat(
Enumerable.Repeat(element,
items.Count() == 0 || items.Last() != element ? 1:0 ))
);
Note to get reasonable performance of above samples with Aggregate you'd need to also carry last value (Last will have to iterate whole sequence on each step), but code that carries 3 values {IsEmpty, LastValue, Sequence} in a Tuple is very strange looking. These samples are here for entertaining purposes only.
One more option is to Zip array with itself shifted by 1 and return elements that are not equal...
More practical option is to build iterator that filters values:
IEnumerable<string> NonRepeated(IEnumerable<string> values)
{
string last = null;
bool lastSet = false;
foreach(var element in values)
{
if (!lastSet || last != element)
{
yield return element;
}
last = element;
lastSet = true;
}
}
check if last of new list and current item is not same then add to new list:
List<string> results = new List<string>();
results.Add(array.First());
foreach (var element in array)
{
if(results[results.Length - 1] != element)
results.Add(element);
}
or using LINQ:
List<int> arr=new List<int>(){1, 2, 3, 4, 4, 4, 1, 1, 2, 3, 4, 4 };
List<int> result = new List<int>() { arr.First() };
arr.Select(x =>
{
if (result[result.Length - 1] != x) result.Add(x);
return x;
}).ToList();
Do have proper validation for null object.
Try this:
class Program
{
static void Main(string[] args)
{
var input = "1, 2, 3, 4, 4, 4, 1, 1, 2, 3, 4, 4 ";
var list = input.Split(',').Select(i => i.Trim());
var result = list
.Select((s, i) =>
(s != list.Skip(i + 1).FirstOrDefault()) ? s : null)
.Where(s => s != null)
.ToList();
}
}
Here the code you need :
public static List<int> RemoveSequencialRepeats(List<int> input)
{
var result = new List<int>();
result.Add(input.First());
result.AddRange(input.Where(p_element => result.Last() != p_element);
return result;
}
The LINQ magic is:
result.Add(input.First());
result.AddRange(input.Where(p_element => result.Last() != p_element);
Or you can create extension method like this:
public static class Program
{
static void Main(string[] args)
{
List<int> numList=new List<int>(){1,2,2,2,4,5,3,2};
numList = numList.RemoveSequentialRepeats();
}
public static List<T> RemoveSequentialRepeats<T>(this List<T> p_input)
{
var result = new List<T> { p_input.First() };
result.AddRange(p_input.Where(p_element => !result.Last().Equals(p_element)));
return result;
}
}
If you feel like referencing an F# project you can write
let rec dedupe = function
| x::y::rest when x = y -> x::dedupe rest
| x::rest -> x::dedupe rest
| _ -> []
I have List with n items. I wish transform my list to new list, in which no more than n first items.
Example for n=3:
[1, 2, 3, 4, 5] => [1, 2, 3]
[1, 2] => [1, 2]
What is the shortest way to do this?
If you have C# 3, use the Take extension method:
var list = new [] {1, 2, 3, 4, 5};
var shortened = list.Take(3);
See: http://msdn.microsoft.com/en-us/library/bb503062.aspx
If you have C# 2, you could write the equivalent:
static IEnumerable<T> Take<T>(IEnumerable<T> source, int limit)
{
foreach (T item in source)
{
if (limit-- <= 0)
yield break;
yield return item;
}
}
The only difference is that it isn't an extension method:
var shortened = SomeClass.Take(list, 3);
If you don't have LINQ, try:
public List<int> GetFirstNElements(List<int> list, int n)
{
n = Math.Min(n, list.Count);
return list.GetRange(0, n);
}
otherwise use Take.
You can use Take
myList.Take(3);
You can with Linq
List<int> myList = new List<int>();
myList.Add(1);
myList.Add(2);
myList.Add(3);
myList.Add(4);
myList.Add(5);
myList.Add(6);
List<int> subList = myList.Take<int>(3).ToList<int>();
var newList = List.Take(3);