Если вы хотите иметь чистое решение 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