C# 空数组上的笛卡尔分布

C# 空数组上的笛卡尔分布,c#,arrays,linq,cartesian,C#,Arrays,Linq,Cartesian,我需要一个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 等等 我目前使用的代码…源自 我试过把MatrixArray\

我需要一个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
等等

我目前使用的代码…源自

我试过把
MatrixArray\n放在第一个位置!=null
但它会在第一个null数组处停止,并且不会读取所有剩余的数组,因此即使填充了数组1和数组3,我的返回数组始终为0行

代码/逻辑的更改此时任何东西都值得赞赏!
TIA

由于Eric的方法是使用
IEnumerable
,因此您必须这样做:

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


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

我是否正确理解您想要排除
第一个
第二个
,等等,如果它们是
空的
?这很简单:

加上

select new [] { first, second, third, fourth, fifth, sixth }.Where(x => x != 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

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

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

(空值,x2,…xn)

下面是一个完整的示例:

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

array1&array2={{null,A},{1,A},{2,A}的笛卡尔积 }

现在,让我们在第一个位置应用过滤器!=空

array1&array2={{1,A},{2,A}的笛卡尔积

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

array1现在={null,null}

带过滤器的array1和array2的笛卡尔积={}


结果是空集。为了得到笛卡尔积,必须从每个数组中获得一个entry。您的问题可以调整以解决这个问题。

从逻辑上讲,当一个或多个数组为空时,您希望发生什么?您是否尝试过用空数组替换空数组?@user1139748空数组与包含空值的数组不同。但是,例如,如果
MatrixArray_1
为空,那么您希望
first
属性中的值是多少?@PaulSasik用空数组替换空数组将不会产生任何结果,因为正如
x*0
产生
0
,因此,一个包含零元素序列的笛卡尔积产生一个零元素序列。你可以创建一个循环,它遍历一个数组(你的六个输入),然后如果它为null或为空,则丢弃该数组,否则做笛卡尔积,然后重复。我想不出任何方法,如果不对每一个数组进行显式的空检查,那么你可以这样做,因为正如phoog指出的那样,试图以任何方式使用一个空集只会清空你的所有结果。我只是在想,最好的方法是,如果矩阵数组在一个可枚举的数组中,允许你轻松地删除那些你不想要的在处理之前。我想我正在慢慢地了解Eric在那个链接上最终得到了什么。当我看到这个答案,看到你的代码与OP非常不同时,我才真正地看了一下链接
var cartesianSequence = sequences
    .Where(s => s != null && s.Any(e => e != null))
    .Select(s => s.Where(v => v != null))
    .CartesianProduct();
select new [] { first, second, third, fourth, fifth, sixth }.Where(x => x != null)
where new [] { first, second, third, fourth, fifth, sixth }.All(x => x != null)