Создание комбинаций в соответствии с положением в списке C # - PullRequest
0 голосов
/ 27 июня 2018

У меня есть список

    var list = new List<record>{
    new record{ flashid = 450, position = 5, value = "a"},
    new record{ flashid = 450, position = 6, value = "b"},
    new record{ flashid = 450, position = 7, value = "c"},
    new record{ flashid = 450, position = 7, value = "d"},
    new record{ flashid = 450, position = 7, value = "e"},
    new record{ flashid = 450, position = 8, value = "f"},
    new record{ flashid = 450, position = 9, value = "g"}
}

У меня 3 записи с позицией 7 с разным значением. Из приведенного выше списка мне нужно создать строку для каждой комбинации в соответствии с позицией от 1 до 10. Для пропущенных значений позиции мы можем иметь любой временный символ. Итак, желаемый результат будет

["....abcfg.","....abdfg.","....abefg."]

у нас может быть любой специальный символ вместо точки.

Спасибо

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Если вы хотите иметь чистое решение LINQ, вы можете попробовать следующее. Прежде всего, расширьте ваш список записей так, чтобы он содержал каждую отсутствующую позицию:

var extendedList = Enumerable
    .Range(1, 10)
    .GroupJoin(list, n => n, r => r.position, (n, g) => g
        .DefaultIfEmpty(new record { flashid = 450, position = n, value = "." }));

Это в основном проходит диапазон от 1 до 10 и для каждого числа, соответствующего позиционным совпадениям и группам записей. Если в группе нет подходящего значения, то есть, когда позиция отсутствует, создается запись по умолчанию с временным символом. Итак, результат выглядит так:

record[10][] 
{ 
    record[] 
    { 
        record { flashid=450, position=1, value="." } 
    },
    (...)
    record[] 
    { 
        record { flashid=450, position=5, value="a" } 
    },
    (...)
    record[] 
    { 
        record { flashid=450, position=7, value="c" },
        record { flashid=450, position=7, value="d" },
        record { flashid=450, position=7, value="e" } 
    },
    (...)
},

Теперь, чтобы сгенерировать все возможные значения, вы можете попробовать это:

var result = extendedList
    .Aggregate(Enumerable.Repeat("", 1), (a, c) => a
        .SelectMany(b => c
            .Select(d => b + d.value)));

Каждая итерация Aggregate преобразует последовательность слов в другую последовательность слов с добавлением одного символа из группы символов в текущей позиции. Итак, это выглядит так:

0. {""}
1. {"."}
2. {"."}
3. {".."}
4. {"..."}
5. {"....a"}
6. {"....ab"}
7. {"....abc", "....abd", "....abe"}
8. {"....abcf", "....abdf", "....abef"}
9. {"....abcfg", "....abdfg", "....abefg"}
10. {"....abcfg.", "....abdfg.", "....abefg."}

Вы можете попробовать это здесь: https://dotnetfiddle.net/JCgYFP

0 голосов
/ 27 июня 2018

Конечно, вы можете решить эту проблему, как описано в ссылках на комментарии к вашему вопросу, но в этом случае вы должны выполнить утомительную работу - написать много повторяющегося кода, например:

var answer = (from pos1 in list.Where(x => x.position == 1)
              from pos2 in list.Where(x => x.position == 2)
              from pos3 in list.Where(x => x.position == 3)
              ....
              from pos10 in list.Where(x => x.position == 10)
              select pos1.value + pos2.value + pos3.value + ... + pos10.value
             ).ToList();

Таким образом, каждый раз, когда вам нужно изменить количество возможных позиций, вы должны добавлять или удалять соответствующие строки кода. Вместо этого вы можете попробовать рекурсивный подход . Прежнее решение не является динамическим - вы должны знать количество позиций заранее во время компиляции, тогда как второе решение может быть просто настроено во время выполнения с помощью limit изменения переменной.

static int limit = 10;

static void Recursive(record record, List<string> bag, 
    Stack<record> stack, List<record> list)
{
    stack.Push(record);
    if (record.position == limit)
    {
        var temp = new StringBuilder();
        foreach (var item in stack)
            temp.Insert(0, item.value);
        bag.Add(temp.ToString());
    }
    else            
        foreach (var item in list.Where(x => x.position == record.position + 1))
            Recursive(item, bag, stack, list);
    stack.Pop();            
}

static List<string> Solve(List<record> list)
{
    for (var i = 1; i <= limit; i++)
        if (!list.Any(x => x.position == i))
             list.Add(new record { position = i, value = "." });

    var bag = new List<string>();
    var stack = new Stack<record>();
    foreach (var record in list.Where(x => x.position == 1))
        Recursive(record, bag, stack, list);

    return bag;
}

Usage:

var list = new List<record>
{
    new record { flashid = 450, position = 5, value = "a"},
    new record { flashid = 450, position = 6, value = "b"},
    new record { flashid = 450, position = 7, value = "c"},
    new record { flashid = 450, position = 7, value = "d"},
    new record { flashid = 450, position = 7, value = "e"},
    new record { flashid = 450, position = 8, value = "f"},
    new record { flashid = 450, position = 9, value = "g"}
};

var answer = Solve(list);       
Console.WriteLine("[" + string.Join(", ", answer) + "]");       
//output: [....abcfg., ....abdfg., ....abefg.]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...