There is already the built-in LINQ method ElementAt, so we could also have an ElementsAt that accepts multiple indices.
public static IEnumerable<TSource> ElementsAt<TSource>(
this IEnumerable<TSource> source, params int[] indices)
{
var indicesHashSet = new HashSet<int>(indices);
return source.Where((x, i) => indicesHashSet.Contains(i));
}
This implementation returns the elements in the order they are found in the source, and ignores duplicate indices.
Usage example:
viewModel.SLGDeptSalesList =
viewModel.SLGDeptSalesList.ElementsAt(1, 3, 4, 6).ToList();
Update: Here is an alternative implementation. This one returns the elements in the order of the indices, and in case of duplicate indices returns duplicate elements. In case of indices out of range no exception is thrown, but no elements are returned for those indices. So it is not guaranteed that the output sequence will have equal length with the requested indices.
public static IEnumerable<TSource> ElementsAt<TSource>(
this IEnumerable<TSource> source, params int[] indices)
{
return indices.Join(source.Select((Item, Index) => (Item, Index)),
i => i, p => p.Index, (_, p) => p.Item);
}
Update: And here is a scholastic variant of the previous implementation. This one guarantees that the requested indices and the output sequence will have equal length. An exception is thrown for indices outside the bounds of the source sequence.
public static IEnumerable<TSource> ElementsAt<TSource>(
this IEnumerable<TSource> source, params int[] indices)
{
var indicesHashSet = new HashSet<int>(indices);
var foundElements = source.Select((Item, Index) => (Item, Index))
.Where(p => indicesHashSet.Contains(p.Index))
.ToDictionary(p => p.Index, p => p.Item);
var notFoundIndices = indices.Where(i => !foundElements.ContainsKey(i)).ToList();
if (notFoundIndices.Count > 0)
throw new ArgumentOutOfRangeException(nameof(indices),
$"Indices [{String.Join(", ", notFoundIndices)}] " +
$"are outside the bounds of the {nameof(source)} sequence.");
return indices.Select(i => foundElements[i]);
}