笛卡尔在NULL数组上

本文关键字:数组 NULL 笛卡尔 | 更新日期: 2023-09-27 18:24:26

我需要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,但它在第一个null数组处停止,并且不会读取所有剩余的数组,因此即使填充了array1和array3,我的返回数组也始终是0行。

代码/逻辑的更改在此时此刻,任何事情都值得赞赏!TIA

笛卡尔在NULL数组上

由于Eric的方法是使用IEnumerable<IEnumerable<T>>,您必须执行以下操作:

Eric的代码:

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调用将排除所有元素都为null的序列。

要排除空数组以及仅包含空值的数组:

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();

编辑

另一种可能性是,您希望排除每个序列的空元素,即使有些元素是非空的:

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();

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

但很难确切知道该建议什么,因为我们不知道你对结果做了什么。

如果firstsecond等是null,那么您想排除它们中的任何一个,我的理解是否正确?这很简单:

只需添加

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

到您的查询。

或者,如果firstsecond等中的任何一个是null,那么您想排除整个六元组吗?这也很容易。只需添加

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

到您的查询。您甚至可以使用let,这样就不会创建两次数组。

根据定义(我引用了前面提到的Eric Lippert博客)。"两个序列S1和S2的笛卡尔乘积是所有可能的两个元素序列的序列,其中第一个元素来自S1,第二个元素来自S2;

如果你将定义概括为:

任意n个序列S1,S2,…的笛卡尔乘积,。。。Sn是所有可能的n元素序列的序列,其中第一个元素来自S1,第二个元素来自S2,n元素来自Sn

请注意,第一个元素应始终来自第一个元素。

如果您要过滤掉第一个数组的空值,这意味着整个entery将丢失,那么过滤掉的entery如下所示:

(空,x2,…xn)

下面是一个完整的例子:

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

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

现在,让我们在First!=无效的

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

假设我们将array1的值更改为:

array1现在={null,null}

array1&array2与过滤器={}

结果为空集。为了得到笛卡尔乘积,你必须从每个数组中得到一个entery。你的问题可以根据这个事实进行调整。