Создавайте уникальные двойники и тройки из коллекции - PullRequest
6 голосов
/ 20 ноября 2011

У меня есть коллекция (List) предметов (String). Количество предметов в этой коллекции всегда будет от 0 до 9.

Мне нужно создать все комбинации пар и троек из этой коллекции. Положение предмета в двойном или тройном значении не имеет значения. Так что {1,2} равно {2,1}.

Как мне этого добиться? Может быть, есть какой-нибудь хороший способ сделать это через LINQ?

1 Ответ

9 голосов
/ 20 ноября 2011

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

Это создает все двойные числа:

string[] items = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" };

var combinations = 
    from a in items
    from b in items
    where a.CompareTo(b) < 0
    orderby a, b
    select new { A = a, B = b };

foreach(var pair in combinations)
    Console.WriteLine("({0}, {1})", pair.A, pair.B);

Это создает все триплеты:

string[] items = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" };

var combinations = 
    from a in items
    from b in items
    from c in items
    where a.CompareTo(b) < 0 && b.CompareTo(c) < 0
    orderby a, b, c
    select new { A = a, B = b, C = c };

foreach(var triplet in combinations)
    Console.WriteLine("({0}, {1}, {2})", triplet.A, triplet.B, triplet.C);

Обновление: Существует универсальное решение для создания всех уникальных подмножеств определенной длины и при этом использование linq.Тем не менее, вам нужен возвращаемый тип, который может содержать подмножество.Я создал простой класс LinkedNode, потому что для меня это наиболее естественно в сочетании с linq:

void Main()
{
    string[] items = { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J" };

    foreach(var combination in CreateCombinations(items, 5))
        Console.WriteLine("({0})", combination.ToString());
}

private static IEnumerable<LinkedNode> CreateCombinations(string[] items, int length)
{
    if(length == 1)
        return items.Select(item => new LinkedNode { Value = item, Next = null });

    return from a in items 
        from b in CreateCombinations(items, length - 1) 
        where a.CompareTo(b.Value) < 0
        orderby a, b.Value
        select new LinkedNode<T> { Value = a, Next = b };
}

public class LinkedNode
{
    public string Value { get; set; }
    public LinkedNode Next { get; set; }

    public override string ToString()
    {
        return (this.Next == null) ? Value : Value + ", " + Next.ToString();
    }
}

Должно быть легко реализовать IEnumerable<string> в классе LinkedNode или преобразовать иным образомСвязанные узлы с List<string> или HashSet<string>.Обратите внимание, что вы можете удалить строку orderby a, b.Value, если порядок не важен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...