Как выбрать значения в пределах предоставленного диапазона индексов из списка с помощью LINQ

Я новичок в LINQ, пытаюсь использовать его для достижения следующих целей:

У меня есть список целых: -

List<int> intList = new List<int>(new int[]{1,2,3,3,2,1});

Теперь я хочу сравнить сумму первых трех элементов [диапазон индекса 0-2] с последними тремя [диапазон индекса 3-5] с помощью LINQ. Я пробовал методы расширения LINQ Select и Take, а также метод SelectMany, но не могу понять, как сказать что-то вроде

(from p in intList  
where p in  Take contiguous elements of intList from index x to x+n  
select p).sum()

Я тоже посмотрел на метод расширения Contains, но он не дает мне того, что я хочу. Какие-либо предложения? Спасибо.


person Punit Vora    schedule 25.06.2009    source источник


Ответы (4)


Используйте Skip, затем Take.

yourEnumerable.Skip(4).Take(3).Select( x=>x )

(from p in intList.Skip(x).Take(n) select p).sum()
person Adam Sills    schedule 25.06.2009
comment
Обратите внимание, что List ‹T› .GetRange будет более эффективным для больших коллекций: icodeit.wordpress.com/2012/08/27/, geekswithblogs.net/BlackRabbitCoder/archive/2012/03/29/ - person nawfal; 25.07.2015
comment
Это хороший, действительный комментарий (так что пару лет назад я поддержал автора ответа ниже, который сказал то же самое), хотя OP спрашивал конкретно о LINQ, поэтому вы не можете действительно гарантировать Список ‹T› в качестве своего источник. Возможно, это была упрощенная версия реальной проблемы, о которой идет речь, где упрощенная версия была просто жестко запрограммированным списком ‹T› (и на самом деле может быть запросом на графе объекта или запросом LINQ to SQL). - person Adam Sills; 27.07.2015
comment
в чем смысл .Select( x=>x )? неужели в этом случае он на самом деле ничего не делает? - person gilad mayani; 02.06.2021

Вы можете использовать GetRange ()

list.GetRange(index, count);
person Onuralp    schedule 10.07.2013
comment
Где эта функция? .NET 4.5 или что-то в этом роде? - person Adam Nofsinger; 09.10.2013
comment
@AdamNofsinger Это находится в пространстве имен System.Collections.Generic. Он пришел с .Net 2.0. msdn.microsoft.com/en-us/library /21k0e39c(v=vs.80).aspx - person Onuralp; 02.07.2014
comment
Стоит отметить, что это есть в интерфейсе IList и поэтому не будет работать с более распространенными IEnumerable. Частично это делается для того, чтобы люди не стреляли в себя с точки зрения производительности ног (то есть, если коллекция не индексируется за время O (1), это может занять время O (n), возможно, неожиданно). Кроме того, он возвращает новый список, а не является фасадом над исходным списком, как это обычно бывает с LINQ. - person Rollie; 27.05.2021

Для больших списков отдельный метод расширения может быть более подходящим для повышения производительности. Я знаю, что в начальном случае это не обязательно, но реализация Linq (для объектов) полагается на итерацию списка, поэтому для больших списков это может быть (бессмысленно) дорого. Простым методом расширения для достижения этого может быть:

public static IEnumerable<TSource> IndexRange<TSource>(
    this IList<TSource> source,
    int fromIndex, 
    int toIndex)
{
    int currIndex = fromIndex;
    while (currIndex <= toIndex)
    {
        yield return source[currIndex];
        currIndex++;
    }
}
person Tao    schedule 05.06.2011

Для фильтрации по определенным индексам (не от-до):

public static class ListExtensions
{
   public static IEnumerable<TSource> ByIndexes<TSource>(this IList<TSource> source, params int[] indexes)
   {        
        if (indexes == null || indexes.Length == 0)
        {
            foreach (var item in source)
            {
                yield return item;
            }
        }
        else
        {
            foreach (var i in indexes)
            {
                if (i >= 0 && i < source.Count)
                    yield return source[i];
            }
        }
   }
}

Например:

string[] list = {"a1", "b2", "c3", "d4", "e5", "f6", "g7", "h8", "i9"};
var filtered = list.ByIndexes(5, 8, 100, 3, 2); // = {"f6", "i9", "d4", "c3"};
person stomy    schedule 12.04.2018