Декартово на NULL массивах - PullRequest
3 голосов
/ 14 февраля 2012

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

мои массивы примерно такие

MatrixArray_1[0] = 1
MatrixArray_1[1] = 2

MatrixArray_2[0] = null
MatrixArray_2[1] = null

MatrixArray_n[0] = 2
MatrixArray_n[1] = 2

и т. Д.

Я использую этокод в настоящее время ... полученный из http://blogs.msdn.com/b/ericlippert/archive/2010/06/28/computing-a-cartesian-product-with-linq.aspx

var product1 =  from first in MatrixArray_1
                from second in MatrixArray_2
                from third in MatrixArray_3
                from fourth in MatrixArray_4
                from fifth in MatrixArray_5
                from sixth in MatrixArray_6
                select new[] { first, second, third, fourth, fifth, sixth };
            string[][] myCombos_linq = product1.ToArray();

Я попытался поместить MatrixArray_n where first != null, но он останавливается на первом нулевом массиве и не читает через все оставшиеся массивы, поэтому мой возвращаемый массив всегда равен 0строки, хотя array1 и array 3 заполнены.

Смена кода / логики в данный момент ценится все что угодно!ТИА

Ответы [ 3 ]

3 голосов
/ 14 февраля 2012

Поскольку подход Эрика заключается в использовании IEnumerable<IEnumerable<T>>, вы должны делать что-то вроде этого:

Код Эрика:

static IEnumerable<IEnumerable<T>> CartesianProduct<T>(this IEnumerable<IEnumerable<T>> sequences) 
{ 
  IEnumerable<IEnumerable<T>> emptyProduct = new[] { Enumerable.Empty<T>() }; 
  return sequences.Aggregate( 
    emptyProduct, 
    (accumulator, sequence) => 
      from accseq in accumulator 
      from item in sequence 
      select accseq.Concat(new[] {item})); 
}

Звоните на сайт:

var sequences = new int?[][] { MatrixArray_1, MatrixArray_2, ..., MatrixArray_6 };
var cartesianSequence = sequences.CartesianProduct();

Изменить сайт звонков:

var cartesianSequence = sequences.Where(a => a.Any(e => e != null)).CartesianProduct();

Вызов Where будет исключать последовательности, в которых все элементы равны нулю.

Чтобы исключить нулевые массивы, а также массивы, содержащие только нулевые значения:

var cartesianSequence = sequences.Where(a => a != null && a.Any(e => e != null)).CartesianProduct();

Или, с пониманием запроса:

var filteredSequences = 
    from sequence in sequences
    where sequence != null && sequence.Any(e => e != null)
    select sequence
var cartesianSequence = filteredSequences.CartesianProduct();

EDIT

Другая возможность состоит в том, что вы хотите исключить нулевые элементы каждой последовательности, даже если некоторые элементы не равны нулю:

var filteredSequences = 
    from sequence in sequences
    where sequence != null && sequence.Any(e => e != null)
    select (from v in sequence where v.HasValue select s)
var cartesianSequence = filteredSequences.CartesianProduct();

OR

var cartesianSequence = sequences
    .Where(s => s != null && s.Any(e => e != null))
    .Select(s => s.Where(v => v != null))
    .CartesianProduct();

Но трудно точно знать, что посоветовать, поскольку мы не знаем, что вы делаете с результатом.

1 голос
/ 14 февраля 2012

Правильно ли я понимаю, что вы хотите исключить какие-либо из first, second и т. Д., Если они null?Это просто:

Просто добавьте

select new [] { first, second, third, fourth, fifth, sixth }.Where(x => x != null)

к вашему запросу.

Или вы хотите исключить весь последовательность, если какой-либо из first, secondи т. д. null?Это тоже легко.Просто добавьте

where new [] { first, second, third, fourth, fifth, sixth }.All(x => x != null)

к вашему запросу.Вы даже можете использовать let, чтобы не создавать массив дважды.

0 голосов
/ 14 февраля 2012

По определению (и я цитирую ранее упомянутый Эрик Липперт блог ). «Декартово произведение двух последовательностей S1 и S2 - это последовательность всех возможных двухэлементных последовательностей, где первый элемент из S1, а второй из S2».

Если обобщить определение, это будет:

Декартово произведение любых n последовательностей S1, S2, ... Sn является последовательностью всех возможных последовательностей n-элементов , где первый элемент из S1 , а второй элемент из S2 и N элемент из Sn

Обратите внимание, что первый элемент ВСЕГДА должен быть от первого элемента.

Если вы фильтруете нулевые значения первого массива, что означает, что вся энтри будет отсутствовать, отфильтрованные энтеросы выглядят так:

(ноль, x2, ... xn)

Вот полный пример:

array1 = {null, 1, 2}
array2 = {A}

Декартово произведение массива1 и массива2 = {{null, A}, {1, A}, {2, A} }

Теперь давайте применим фильтр, где First! = Null.

Декартово произведение массива1 и массива2 = {{1, A}, {2, A}}

Скажите, что мы изменили значение массива1 на:

array1 now = {null, null}

Декартово произведение массивов1 и массив2 с фильтром = {}

Результат - пустой набор. Чтобы получить декартово произведение, вы должны иметь энтерос из каждого массива. Ваш вопрос может быть скорректирован с учетом этого факта.

...