我怎样才能得到一系列bool组合,从最小的trues到大多数trues?

Evo*_*lor 4 c# arrays combinations boolean unity5

我正在尝试创建一个bool数组的数组.我希望除了具有bool数组的每个组合{false, false, false, false}.我希望这个数组的顺序保持它的子数组,使它以最小的数量顺序上升到大多数真实状态.(向后订单很好,但仍然必须订购.)

阵列的每个子集使得它们具有相同数量的trues应该是随机顺序的.

我可以这样硬编码:

private bool[][] GetBoolArrays()
{
    var fourDoorList = new List<bool[]>();
    fourDoorList.Add(new bool[4] { true, true, true, true });
    fourDoorList = fourDoorList.OrderBy(c => Random.Range(float.MinValue, float.MaxValue)).ToList();
    var threeDoorList = new List<bool[]>();
    threeDoorList.Add(new bool[4] { true, true, true, false });
    threeDoorList.Add(new bool[4] { true, true, false, true });
    threeDoorList.Add(new bool[4] { true, false, true, true });
    threeDoorList.Add(new bool[4] { false, true, true, true });
    threeDoorList = threeDoorList.OrderBy(c => Random.Range(float.MinValue, float.MaxValue)).ToList();
    var twoDoorList = new List<bool[]>();
    twoDoorList.Add(new bool[4] { true, true, false, false });
    twoDoorList.Add(new bool[4] { true, false, true, false });
    twoDoorList.Add(new bool[4] { true, false, false, true });
    twoDoorList.Add(new bool[4] { false, true, true, false });
    twoDoorList.Add(new bool[4] { false, true, false, true });
    twoDoorList.Add(new bool[4] { false, false, true, true });
    twoDoorList = twoDoorList.OrderBy(c => Random.Range(float.MinValue, float.MaxValue)).ToList();
    var oneDoorList = new List<bool[]>();
    oneDoorList.Add(new bool[4] { true, false, false, false });
    oneDoorList.Add(new bool[4] { false, true, false, false });
    oneDoorList.Add(new bool[4] { false, false, true, false });
    oneDoorList.Add(new bool[4] { false, false, false, true });
    oneDoorList = oneDoorList.OrderBy(c => Random.Range(float.MinValue, float.MaxValue)).ToList();
    var boolArrayList = new List<bool[]>();
    boolArrayList.AddRange(fourDoorList);
    boolArrayList.AddRange(threeDoorList);
    boolArrayList.AddRange(twoDoorList);
    boolArrayList.AddRange(oneDoorList);
    return boolArrayList.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

但那太脏了!

我可以创建一个这样的列表,但这些列表按我想要的方式排序:

private bool[][] GetBoolArrays()
{
    const int subArraySize = 4;
    bool[][] combinations = new bool[(int)Mathf.Pow(2, subArraySize) - 1][];
    for (int i = 1; i < Mathf.Pow(2, subArraySize); i++)
    {
        string binary = System.Convert.ToString(i, 2);
        while (binary.Length < subArraySize)
        {
            binary = 0 + binary;
        }
        bool[] singleCombination = binary.Select(c => c == '1').ToArray();
        combinations[i - 1] = singleCombination;
    }
    return combinations;
}
Run Code Online (Sandbox Code Playgroud)

所以为了澄清,我正在尝试创建一个数组数组.每个子阵列有4个bool.除了所有false之外,主数组具有子数组的每个组合.子阵列应按真实数量排序,但每个具有一定数量的真实性的部分应随机化.

如果这是对我所追求的不好解释,我道歉...这有点难以解释.我可以澄清任何需要的东西.关于如何清理硬编码版本的任何想法?

Eri*_*ert 11

让我们做一系列小的重构.我们从:

private bool[][] GetBoolArrays()
{
    var fourDoorList = new List<bool[]>();
    fourDoorList.Add(new bool[4] { true, true, true, true });
    fourDoorList = fourDoorList.OrderBy(c => Random.Range(float.MinValue, float.MaxValue)).ToList();
    var threeDoorList = new List<bool[]>();
    threeDoorList.Add(new bool[4] { true, true, true, false });
    threeDoorList.Add(new bool[4] { true, true, false, true });
    threeDoorList.Add(new bool[4] { true, false, true, true });
    threeDoorList.Add(new bool[4] { false, true, true, true });
    threeDoorList = threeDoorList.OrderBy(c => Random.Range(float.MinValue, float.MaxValue)).ToList();
    var twoDoorList = new List<bool[]>();
    twoDoorList.Add(new bool[4] { true, true, false, false });
    twoDoorList.Add(new bool[4] { true, false, true, false });
    twoDoorList.Add(new bool[4] { true, false, false, true });
    twoDoorList.Add(new bool[4] { false, true, true, false });
    twoDoorList.Add(new bool[4] { false, true, false, true });
    twoDoorList.Add(new bool[4] { false, false, true, true });
    twoDoorList = twoDoorList.OrderBy(c => Random.Range(float.MinValue, float.MaxValue)).ToList();
    var oneDoorList = new List<bool[]>();
    oneDoorList.Add(new bool[4] { true, false, false, false });
    oneDoorList.Add(new bool[4] { false, true, false, false });
    oneDoorList.Add(new bool[4] { false, false, true, false });
    oneDoorList.Add(new bool[4] { false, false, false, true });
    oneDoorList = oneDoorList.OrderBy(c => Random.Range(float.MinValue, float.MaxValue)).ToList();
    var boolArrayList = new List<bool[]>();
    boolArrayList.AddRange(fourDoorList);
    boolArrayList.AddRange(threeDoorList);
    boolArrayList.AddRange(twoDoorList);
    boolArrayList.AddRange(oneDoorList);
    return boolArrayList.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

我们注意到的第一件事是重复的洗牌代码.将其解压缩到辅助扩展名.另外,为什么我们需要把它变成一个列表?我们稍后将把它传递给AddRange.将其保留为序列.

static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items)
{
  return items.OrderBy(c => Random.Range(float.MinValue, float.MaxValue));
}
Run Code Online (Sandbox Code Playgroud)

此外,我们现在有一个洗牌序列和一个未洗牌的列表.保持它们单独的变量.

另外,我们注意到列表中没有任何内容,只有一件事在其中!

好的,现在我们得到了什么?

private bool[][] GetBoolArrays()
{
    var fourDoorList = new List<bool[]>();
    fourDoorList.Add(new bool[4] { true, true, true, true });
    var fourDoorListShuffle = fourDoorList; // No point shuffling!
    var threeDoorList = new List<bool[]>();
    threeDoorList.Add(new bool[4] { true, true, true, false });
    threeDoorList.Add(new bool[4] { true, true, false, true });
    threeDoorList.Add(new bool[4] { true, false, true, true });
    threeDoorList.Add(new bool[4] { false, true, true, true });
    var threeDoorListShuffle = threeDoorList.Shuffle();
    var twoDoorList = new List<bool[]>();
    twoDoorList.Add(new bool[4] { true, true, false, false });
    twoDoorList.Add(new bool[4] { true, false, true, false });
    twoDoorList.Add(new bool[4] { true, false, false, true });
    twoDoorList.Add(new bool[4] { false, true, true, false });
    twoDoorList.Add(new bool[4] { false, true, false, true });
    twoDoorList.Add(new bool[4] { false, false, true, true });
    var twoDoorListShuffle = twoDoorList.Shuffle();
    var oneDoorList = new List<bool[]>();
    oneDoorList.Add(new bool[4] { true, false, false, false });
    oneDoorList.Add(new bool[4] { false, true, false, false });
    oneDoorList.Add(new bool[4] { false, false, true, false });
    oneDoorList.Add(new bool[4] { false, false, false, true });
    var oneDoorListShuffle = oneDoorList.Shuffle();
    var boolArrayList = new List<bool[]>();
    boolArrayList.AddRange(fourDoorListShuffle);
    boolArrayList.AddRange(threeDoorListShuffle);
    boolArrayList.AddRange(twoDoorListShuffle);
    boolArrayList.AddRange(oneDoorListShuffle);
    return boolArrayList.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

我们还注意到了什么?我们说"new bool [4]"但编译器可以推断出类型和数字.

private bool[][] GetBoolArrays()
{
    var fourDoorList = new List<bool[]>();
    fourDoorList.Add(new[] { true, true, true, true });
    var fourDoorListShuffle = fourDoorList; // No point shuffling!
    var threeDoorList = new List<bool[]>();
    threeDoorList.Add(new[] { true, true, true, false });
    threeDoorList.Add(new[] { true, true, false, true });
    threeDoorList.Add(new[] { true, false, true, true });
    threeDoorList.Add(new[] { false, true, true, true });
    var threeDoorListShuffle = threeDoorList.Shuffle();
    var twoDoorList = new List<bool[]>();
    twoDoorList.Add(new[] { true, true, false, false });
    twoDoorList.Add(new[] { true, false, true, false });
    twoDoorList.Add(new[] { true, false, false, true });
    twoDoorList.Add(new[] { false, true, true, false });
    twoDoorList.Add(new[] { false, true, false, true });
    twoDoorList.Add(new[] { false, false, true, true });
    var twoDoorListShuffle = twoDoorList.Shuffle();
    var oneDoorList = new List<bool[]>();
    oneDoorList.Add(new[] { true, false, false, false });
    oneDoorList.Add(new[] { false, true, false, false });
    oneDoorList.Add(new[] { false, false, true, false });
    oneDoorList.Add(new[] { false, false, false, true });
    var oneDoorListShuffle = oneDoorList.Shuffle();
    var boolArrayList = new List<bool[]>();
    boolArrayList.AddRange(fourDoorListShuffle);
    boolArrayList.AddRange(threeDoorListShuffle);
    boolArrayList.AddRange(twoDoorListShuffle);
    boolArrayList.AddRange(oneDoorListShuffle);
    return boolArrayList.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

更好.如果我们使用集合初始化程序而不是所有这些对Add的调用怎么办?

private bool[][] GetBoolArrays()
{
    var fourDoorList = new List<bool[]>() {
      new[] { true, true, true, true }};
    var fourDoorListShuffle = fourDoorList; // No point shuffling!
    var threeDoorList = new List<bool[]>() {
      new[] { true, true, true, false },
      new[] { true, true, false, true },
      new[] { true, false, true, true },
      new[] { false, true, true, true }};
    var threeDoorListShuffle = threeDoorList.Shuffle();
    var twoDoorList = new List<bool[]>() {
      new[] { true, true, false, false },
      new[] { true, false, true, false },
      new[] { true, false, false, true },
      new[] { false, true, true, false },
      new[] { false, true, false, true },
      new[] { false, false, true, true }};
    var twoDoorListShuffle = twoDoorList.Shuffle();
    var oneDoorList = new List<bool[]>() {
      new[] { true, false, false, false },
      new[] { false, true, false, false },
      new[] { false, false, true, false },
      new[] { false, false, false, true }};
    var oneDoorListShuffle = oneDoorList.Shuffle();
    var boolArrayList = new List<bool[]>();
    boolArrayList.AddRange(fourDoorListShuffle);
    boolArrayList.AddRange(threeDoorListShuffle);
    boolArrayList.AddRange(twoDoorListShuffle);
    boolArrayList.AddRange(oneDoorListShuffle);
    return boolArrayList.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

更好.我们需要解释变量是什么?

private bool[][] GetBoolArrays()
{
    var fourDoorList = new List<bool[]>() {
      new[] { true, true, true, true }};
    var threeDoorList = new List<bool[]>() {
      new[] { true, true, true, false },
      new[] { true, true, false, true },
      new[] { true, false, true, true },
      new[] { false, true, true, true }};
    var twoDoorList = new List<bool[]>() {
      new[] { true, true, false, false },
      new[] { true, false, true, false },
      new[] { true, false, false, true },
      new[] { false, true, true, false },
      new[] { false, true, false, true },
      new[] { false, false, true, true }};
    var oneDoorList = new List<bool[]>() {
      new[] { true, false, false, false },
      new[] { false, true, false, false },
      new[] { false, false, true, false },
      new[] { false, false, false, true }};
    var boolArrayList = new List<bool[]>();
    boolArrayList.AddRange(fourDoorList);
    boolArrayList.AddRange(threeDoorList.Shuffle());
    boolArrayList.AddRange(twoDoorList.Shuffle());
    boolArrayList.AddRange(oneDoorList.Shuffle());
    return boolArrayList.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

嗯,为什么所有的这些都被列出?

private bool[][] GetBoolArrays()
{
    var fourDoorList = new[] {
      new[] { true, true, true, true }};
    var threeDoorList = new[] {
      new[] { true, true, true, false },
      new[] { true, true, false, true },
      new[] { true, false, true, true },
      new[] { false, true, true, true }};
    var twoDoorList = new[] {
      new[] { true, true, false, false },
      new[] { true, false, true, false },
      new[] { true, false, false, true },
      new[] { false, true, true, false },
      new[] { false, true, false, true },
      new[] { false, false, true, true }};
    var oneDoorList = new[] {
      new[] { true, false, false, false },
      new[] { false, true, false, false },
      new[] { false, false, true, false },
      new[] { false, false, false, true }};
    var boolArrayList = new List<bool[]>();
    boolArrayList.AddRange(fourDoorList);
    boolArrayList.AddRange(threeDoorList.Shuffle());
    boolArrayList.AddRange(twoDoorList.Shuffle());
    boolArrayList.AddRange(oneDoorList.Shuffle());
    return boolArrayList.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

添加范围序列与连续序列相同:

private bool[][] GetBoolArrays()
{
    var fourDoorList = new[] {
      new[] { true, true, true, true }};
    var threeDoorList = new[] {
      new[] { true, true, true, false },
      new[] { true, true, false, true },
      new[] { true, false, true, true },
      new[] { false, true, true, true }};
    var twoDoorList = new[] {
      new[] { true, true, false, false },
      new[] { true, false, true, false },
      new[] { true, false, false, true },
      new[] { false, true, true, false },
      new[] { false, true, false, true },
      new[] { false, false, true, true }};
    var oneDoorList = new[] {
      new[] { true, false, false, false },
      new[] { false, true, false, false },
      new[] { false, false, true, false },
      new[] { false, false, false, true }};
    return fourDoorList.
      Concat(threeDoorList.Shuffle()).
      Concat(twoDoorList.Shuffle()).
      Concat(oneDoorList.Shuffle()).
      ToArray();
}
Run Code Online (Sandbox Code Playgroud)

这比原始代码更好看.请注意我们如何简单地进行一系列清晰,正确的重构,使每个修订版更好一些.

现在,你能用一种方法来获得你想要的总数,你想要的数字是多少?

static IEnumerable<bool[]> Combinations(int totalCount, int trueCount) 
{ 
    You implement this
}
Run Code Online (Sandbox Code Playgroud)

假设我们有这样一种方法,这是一种练习.(我博客上的组合文章可能有帮助.)

现在我们可以写:

private bool[][] GetBoolArrays()
{
    var fourDoorList = Combinations(4, 4);
    var threeDoorList = Combinations(4, 3);
    var twoDoorList = Combinations(4, 2);
    var oneDoorList = Combinations(4, 1);
    return fourDoorList.
      Concat(threeDoorList.Shuffle()).
      Concat(twoDoorList.Shuffle()).
      Concat(oneDoorList.Shuffle()).
      ToArray();
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以编写一个具有此签名的方法:

static IEnumerable<T> MultiConcat(IEnumerable<IEnumerable<T>> sequences) 
{
   ... you implement this ...
}
Run Code Online (Sandbox Code Playgroud)

如果可以,那么你可以写:

private bool[][] GetBoolArrays()
{
    var combinations = new[] {
      Combinations(4, 4).Shuffle(),
      Combinations(4, 3).Shuffle(),
      Combinations(4, 2).Shuffle(),
      Combinations(4, 1).Shuffle()};
    return combinations.MultiConcat().ToArray();
}
Run Code Online (Sandbox Code Playgroud)

我认为这比原始代码更容易阅读.事实上,我们可以将其归结为一个声明:

private bool[][] GetBoolArrays()
{
    return new[] 
    {
      Combinations(4, 4).Shuffle(),
      Combinations(4, 3).Shuffle(),
      Combinations(4, 2).Shuffle(),
      Combinations(4, 1).Shuffle()
    }.MultiConcat().ToArray();
}
Run Code Online (Sandbox Code Playgroud)

但现在我们可能会变得过于简洁.

但是现在不要停止.那里有很多重复的代码!

private bool[][] GetBoolArrays()
{
  var q = from num in new[] { 4, 3, 2, 1 }
          select Combinations(4, num).Shuffle();
  return q.MultiConcat().ToArray();
}
Run Code Online (Sandbox Code Playgroud)

哦等等,我们已经在LINQ中内置了一个多联接!嘿,很抱歉让你做这个练习,但我打赌它建立了性格.

private bool[][] GetBoolArrays()
{
  var q = from num in new[] { 4, 3, 2, 1 }
          select Combinations(4, num).Shuffle() into all
          from combinations in all
          from combination in combinations
          select combination;
  return q.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

这就像我要做的那样简洁.

请注意这里的课程:

  • 迭代的小变化可以带来很大的结果.
  • 将操作提取到专门处理这些操作的方法
  • 使用编译器推断来减少冗余并提高可读性
  • 使用表达式来描述值的代码通常比使用语句来描述操作的代码更紧凑.
  • 拥抱抽象.请注意,当我们放弃将所有东西都填入列表的愿望时,一切都变得容易了.
  • 如果您要将事物变成列表或数组,请尽可能在过程的后期执行.

  • 不使用`Enumerable.Range`来创建从4到1的数字数组?(我意识到字符数可能会上升,而不是下降,但它代表操作的语义比硬编码更好.) (2认同)