Принимать параметры, которые сами по себе являются списками?

Я пытаюсь написать метод для проекта, который принимает любое количество списков в качестве параметров и возвращает новый список, содержащий термины, которые разделяют ВСЕ эти списки. У меня есть функциональный код, но я бы предпочел использовать ключевое слово params, а не создавать список списков, содержащий все списки, которые я хочу сравнить.

static List<T> Shared<T>(List<T> first, List<T> second)
{
    List<T> result = new List<T>();
    foreach (T item in first)
        if (second.Contains(item) && !result.Contains(item)) result.Add(item);
    return result;
}

static List<T> Shared<T>(List<List<T>> lists)
{
    List<T> result = lists.First();

    foreach (List<T> list in lists.Skip(1))
    {
        result = Shared<T>(result, list);
    }

    return result;
}

Это мой текущий код, который отлично работает при сравнении двух списков, но для сравнения более двух списков мне нужно либо создать новый список, например:

List<int> nums1 = new List<int> { 1, 2, 3, 4, 5, 6 };
List<int> nums2 = new List<int> { 1, 2, 3 };
List<int> nums3 = new List<int> { 6, 5, 3, 2 };

List<int> listOfLists = Shared<int>(new List<List<int>> {nums1, nums2, nums3});

foreach (int item in listOfLists)
    Console.WriteLine(item);

//Writes 2 and 3

и т. д. Я действительно хотел бы просто иметь возможность использовать Shared (list1, list2, list3, list4 ...) вместо этого, даже если этот код уже в некоторой степени функционален. В настоящее время при любых попытках использования версии с параметрами сообщается, что «Нет перегрузки для метода 'Shared', который принимает N аргументов».

Также я знаю, что мой код, вероятно, можно было бы сделать более эффективно, поэтому я был бы рад увидеть предложения по этому поводу, но в первую очередь мне нужно понять, почему использование параметров не работает - если это вообще возможно.


person Jacob Cheatley    schedule 13.08.2014    source источник
comment
Почему вы не просто используете _1 _ вместо этого первого метода?   -  person Damien_The_Unbeliever    schedule 13.08.2014
comment
@Damien_The_Unbeliever Я думаю, это не союз, это Пересечение   -  person Sriram Sakthivel    schedule 13.08.2014


Ответы (3)


Вы это ищете?

static List<T> Shared<T>(params List<T>[] lists)

Параметр params всегда должен иметь тип массив, но это может быть массив списков.

person Selman Genç    schedule 13.08.2014
comment
ну, теперь я чувствую себя НЕВЕРОЯТНО глупо. Спасибо большое :) - person Jacob Cheatley; 13.08.2014
comment
По-видимому, планируется изменить это, когда C # 6 прибыл (см. Params IEnumerable) - person Damien_The_Unbeliever; 13.08.2014

Это легко сделать тихо:

using System.Linq;
// ..
static List<T> Shared<T>(params List<T>[] lists)
{
    if (lists == null)
    {
        throw new ArgumentNullException("lists");
    }  

    return Shared(lists.ToList());
}
person Community    schedule 13.08.2014

Основываясь на ответе @ Selman22, который предложил подпись метода, вы также можете использовать этот запрос LINQ для достижения желаемого результата.

static List<T> Shared<T>(params List<T>[] lists)
{
    return 
        lists.Skip(1).Aggregate(    // Skip first array item, because we use it as a seed anyway
        lists.FirstOrDefault(), // Seed the accumulator with first item in the array
        (accumulator, currentItem) => accumulator.Intersect(currentItem).ToList());  // Intersect each item with the previous results
}

Мы пропускаем первый элемент, который используется в качестве начального числа для аккумулятора, и делаем пересечение с аккумулятором для каждого элемента в данном массиве params, поскольку только элементы, содержащиеся во ВСЕХ списках, сохраняются в результате аккумулятора.

Чтобы проверить это, вы можете использовать

Shared(nums1, nums2, nums3).ForEach(r => Console.WriteLine(r));
person Andrej Kikelj    schedule 13.08.2014