Вычислите ряд связанных наборов наборов n

Хорошо - я даже не уверен, что слово является правильным - и я уверен, там обязан быть термином для этого - но я приложу все усилия для объяснения. Это - не совсем векторное произведение здесь, и порядок результатов абсолютно крайне важен.

Данный:

IEnumerable<IEnumerable<string>> sets = 
      new[] { 
              /* a */ new[] { "a", "b", "c" },
              /* b */ new[] { "1", "2", "3" },
              /* c */ new[] { "x", "y", "z" }
            };

Где каждый внутренний счетный представляет инструкцию произвести ряд конкатенаций следующим образом (порядок здесь важен):

set a* = new string[] { "abc", "ab", "a" };
set b* = new string[] { "123", "12", "1" };
set c* = new string[] { "xyz", "xy", "x" };

Я хочу произвести набор, заказанный конкатенации следующим образом:

set final = new string { a*[0] + b*[0] + c*[0], /* abc123xyz */
                         a*[0] + b*[0] + c*[1], /* abc123xy  */
                         a*[0] + b*[0] + c*[2], /* abc123x   */
                         a*[0] + b*[0],         /* abc123    */
                         a*[0] + b*[1] + c*[0], /* abc12xyz  */
                         a*[0] + b*[1] + c*[1], /* abc12xy   */
                         a*[0] + b*[1] + c*[2], /* abc12x    */
                         a*[0] + b*[1],         /* abc12     */
                         a*[0] + b*[2] + c*[0], /* abc1xyz   */
                         a*[0] + b*[2] + c*[1], /* abc1xy    */
                         a*[0] + b*[2] + c*[2], /* abc1x     */
                         a*[0] + b*[2],         /* abc1      */
                         a*[0],                 /* abc       */
                         a*[1] + b*[0] + c*[0], /* ab123xyz  */

                         /* and so on for a*[1] */
                         /* ... */

                         a*[2] + b*[0] + c*[0], /* a123xyz   */

                         /* and so on for a*[2] */
                         /* ... */

                         /* now lop off a[*] and start with b + c */

                         b*[0] + c*[0],         /* 123xyz    */

                         /* rest of the combinations of b + c
                            with b on its own as well */

                         /* then finally */
                         c[0],
                         c[1],
                         c[2]};

Так ясно, там будут большим количеством комбинаций!

Я вижу общие черты с Числовыми основаниями (так как порядок важен также), и я уверен, что существуют перестановки/комбинации, скрывающиеся в здесь также.

Вопрос - как записать алгоритм как это, это справится с каким-либо количеством наборов строк? Linq, non-Linq; я не суечусь.

Почему я делаю это?

Действительно, почему!?

У Asp. Сетевой MVC - я хочу иметь частичные представления, которые могут быть переопределены для данной комбинации культуры бэкэнда/фронтенда и языка. Самый основной из них был бы для высказанного основного мнения View, мы могли иметь View-en-GB, View-en, View-GB, и View, в том порядке очередности (распознающий, конечно, что язык/культурные коды мог быть тем же, так некоторые комбинации могли бы быть тем же - a Distinct() решит это).

Но у меня также есть другие представления, которые, в себе, имеют другие возможные комбинации, прежде чем культура будет даже принята во внимание (слишком долго для входа - но факт, этот алгоритм включит целый набор действительно прохладного, что я хочу предложить моим разработчикам!).

Я хочу произвести поисковый список всех приемлемых имен представления, выполнить итерации через всех, пока самое определенное соответствие не найдено (управляемый порядком, что этот алгоритм произведет эти конкатенации в), затем подают разрешенное Частичное Представление.

Результат поиска может позже кэшироваться для предотвращения расхода выполнения алгоритма все время.

У меня уже есть действительно базовая версия этой работы, которая просто имеет одну счетную из строк. Но это - совершенно другой чайник морепродуктов!

Любая справка значительно ценится.

5
задан svick 10 June 2010 в 12:10
поделиться

3 ответа

Вот моя попытка:

void Main()
{
    IEnumerable<IEnumerable<string>> sets = 
          new[] { 
                  /* a */ new[] { "a", "b", "c" },
                  /* b */ new[] { "1", "2", "3" },
                  /* c */ new[] { "x", "y", "z" }
                };

    var setCombinations = from set in sets
                          select (from itemLength in Enumerable.Range(1, set.Count()).Reverse()
                                  select string.Concat(set.Take(itemLength).ToArray()));

    IEnumerable<string> result = new[] { string.Empty };

    foreach (var list in setCombinations) {
        result = GetCombinations(result, list);
    }
    // do something with the result
}

IEnumerable<string> GetCombinations(IEnumerable<string> root, IEnumerable<string> append) {
    return from baseString in root
           from combination in ((from str in append select baseString + str).Concat(new [] { baseString }))
           select combination;
}
3
ответ дан 14 December 2019 в 13:26
поделиться

Это должно дать то, что вы хотите:

using System;
using System.Linq;
using System.Collections.Generic;

namespace SO3014119
{
    class Program
    {
        private static IEnumerable<string> GetStringCombinations(
            string prefix, 
            IEnumerable<string>[] collections, int startWithIndex)
        {
            foreach (var element in collections[startWithIndex])
            {
                if (startWithIndex < collections.Length - 1)
                {
                    foreach (var restCombination in
                        GetStringCombinations(prefix + element, collections,
                            startWithIndex + 1))
                    {
                        yield return restCombination;
                    }
                }

                yield return prefix + element;
            }
        }

        public static IEnumerable<string> GetStringCombinations(
            params IEnumerable<string>[] collections)
        {
            while (collections.Length > 0)
            {
                foreach (var comb in GetStringCombinations("", collections, 0))
                    yield return comb;

                // "lop off" head and iterate
                collections = collections.Skip(1).ToArray();
            }
        }

        static void Main(string[] args)
        {
            var a = new string[] { "a1", "a2", "a3" };
            var b = new string[] { "b1", "b2", "b3" };
            var c = new string[] { "c1", "c2", "c3" };

            foreach (string combination in GetStringCombinations(a, b, c))
            {
                Console.Out.WriteLine(combination);
            }
        }
    }
}

Это производит (обратите внимание, я изменил записи во входных коллекциях, чтобы сделать легче увидеть, как они были объединены):

a1b1c1
a1b1c2
a1b1c3
a1b1
a1b2c1
a1b2c2
a1b2c3
a1b2
a1b3c1
a1b3c2
a1b3c3
a1b3
a1
a2b1c1
a2b1c2
a2b1c3
a2b1
a2b2c1
a2b2c2
a2b2c3
a2b2
a2b3c1
a2b3c2
a2b3c3
a2b3
a2
a3b1c1
a3b1c2
a3b1c3
a3b1
a3b2c1
a3b2c2
a3b2c3
a3b2
a3b3c1
a3b3c2
a3b3c3
a3b3
a3
b1c1
b1c2
b1c3
b1
b2c1
b2c2
b2c3
b2
b3c1
b3c2
b3c3
b3
c1
c2
c3
2
ответ дан 14 December 2019 в 13:26
поделиться

Решение кажется простым (алгоритмически)

Добавить внешнюю пустую строку в конец каждого массива a *, b *, c *

string[] a* = { "abc","ab","a","" };
string[] b* = { "123","12","1","" };
string[] c* = { "xyz","xy","x","" };

List<string> final = new List<string>();

Теперь сделайте информационное сообщение для трех массивов

foreach(string aMember in a*)
foreach(string bMember in b*)
foreach(string cMember in c*)
final.add(aMember+bMember+cMember);

Дополнительная пустая строка в конце a *, b * и c * будет генерировать специальные строки, такие как a [0] (= a [0 ] + b [3] + c [3]) в нужном порядке.

РЕДАКТИРОВАТЬ: этот код создаст дополнительные строки. См. Комментарий ниже.

1
ответ дан 14 December 2019 в 13:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: