Есть алфавит в виде произвольного массива 'a'...'z' и выходная длина N.
Возможно ли написать алгоритм перебора ("a..aa", "a..ab", .. , "z..zz") в виде чистого linq выражения без использования явных циклов и дополнительных контейнеров, которое будет лениво выводить одно за другим все значения?
string[] ss = new string[] {"a", "b", "c"};
int N = 3;
var result = from ss select ?;
foreach (var x in result)
{
Console.WriteLine(x); // "aaa" — "zzz"
}
Чувствую, что тут нужен SelectMany, но пока данный орешек не поддается.
Здравствуйте, Maru, Вы писали:
M>Чувствую, что тут нужен SelectMany, но пока данный орешек не поддается.
Решение в лоб:
static void Main(string[] args)
{
string[] ss = new string[] { "a", "b", "c" };
int N = 3;
var result = ss.AsEnumerable();
for (int i = 1; i < N; i++)
{
result = result.SelectMany(s => ss.Select(s1 => s + s1));
}
foreach (var item in result)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
У Липперта была целая серия статей на связанную тему, вот первая. Я их скорее пролистал, чем прочитал, так что сходу не вспомню есть ли там готовое решение.
Здравствуйте, Maru, Вы писали:
M>Есть алфавит в виде произвольного массива 'a'...'z' и выходная длина N. M>Возможно ли написать алгоритм перебора ("a..aa", "a..ab", .. , "z..zz") в виде чистого linq выражения без использования явных циклов и дополнительных контейнеров, которое будет лениво выводить одно за другим все значения?
Используй рекурсию, Люк!
Re[2]: Алгоритм перебора на LINQ
От:
Аноним
Дата:
03.02.14 13:37
Оценка:
Здравствуйте, Sinix, Вы писали:
S>Решение в лоб: S>
S> static void Main(string[] args)
S> {
S> string[] ss = new string[] { "a", "b", "c" };
S> int N = 3;
S> var result = ss.AsEnumerable();
S> for (int i = 1; i < N; i++)
S> {
S> result = result.SelectMany(s => ss.Select(s1 => s + s1));
S> }
S> foreach (var item in result)
S> {
S> Console.WriteLine(item);
S> }
S> Console.ReadKey();
S> }
S>
S>У Липперта была целая серия статей на связанную тему, вот первая. Я их скорее пролистал, чем прочитал, так что сходу не вспомню есть ли там готовое решение.
Такое решение более-менее очевидно, спасибо. Мне хочется, чтобы не было промежуточных результатов, и чтобы было полностью ленивое решение.
Здравствуйте, Maru, Вы писали:
M>Чувствую, что тут нужен SelectMany, но пока данный орешек не поддается.
Без SelectMany:
static void Main(string[] args)
{
string[] ss = new string[] { "a", "b", "c" };
int N = 3;
var result = Enumerable.Repeat(0, N-1)
.Aggregate(ss.AsEnumerable(), (res, i) => res.Join(ss, a => 0, a => 0, (a, b) => a + b));
foreach (var s in result)
{
Console.WriteLine(s);
}
Console.ReadKey();
}
Цикл в решении от Sinix так же можно переделать через Enumerable.Repeat(0, N-1).
Здравствуйте, Аноним, Вы писали:
А>Такое решение более-менее очевидно, спасибо. Мне хочется, чтобы не было промежуточных результатов, и чтобы было полностью ленивое решение.
А там и нет промежуточных результатов. Выражение начинает вычисляться только в момент foreach. Так что, с циклом решение тоже ленивое, в нем нет вычислений, а только построение выражения.