我正在尝试创建一个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();
}
但那太脏了!
我可以创建一个这样的列表,但这些列表按我想要的方式排序:
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;
}
因此,为了澄清,我正在尝试创建一个数组数组。每个子阵列有4个bool。除了所有false之外,主数组具有子数组的每个组合。子阵列应按真实数量排序,但每个具有一定数量的真实性的部分应随机化。
如果这是对我所追求的不好解释,我道歉......这有点难以解释。我可以澄清任何需要的东西。关于如何清理硬编码版本的任何想法?
答案 0 :(得分: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();
}
我们注意到的第一件事是重复的洗牌代码。将其解压缩到辅助扩展名。另外,为什么我们需要把它变成一个列表?我们稍后将把它传递给AddRange。将其保留为序列。
static IEnumerable<T> Shuffle<T>(this IEnumerable<T> items)
{
return items.OrderBy(c => Random.Range(float.MinValue, float.MaxValue));
}
此外,我们现在有一个洗牌序列和一个未洗牌的列表。保持它们是单独的变量。
另外,我们注意到列表中没有任何内容,只有一件事在其中!
好的,现在我们得到了什么?
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();
}
我们还注意到了什么?我们说&#34;新布尔[4]&#34;但编译器可以推断出类型和数字。
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();
}
更好。如果我们使用集合初始化程序而不是所有这些对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();
}
更好。我们需要解释变量是什么?
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();
}
嗯,为什么中的任何必须是列表?
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();
}
添加范围序列与连续序列相同:
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();
}
看起来比原始代码更好看。请注意我们如何简单地制作一系列清晰,正确的重构,使每个修订版更好一些。
现在,您是否可以制作一个方法来获取您想要的总数,以及您想要的数字?
static IEnumerable<bool[]> Combinations(int totalCount, int trueCount)
{
You implement this
}
假设我们有这样一种方法,这是一种练习。 (我博客上的组合文章可能有所帮助。)
现在我们可以写:
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();
}
现在,您可以编写一个具有此签名的方法:
static IEnumerable<T> MultiConcat(IEnumerable<IEnumerable<T>> sequences)
{
... you implement this ...
}
如果可以,那么你可以写:
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();
}
我认为这比原始代码更容易阅读。事实上,我们可以将其归结为一个声明:
private bool[][] GetBoolArrays()
{
return new[]
{
Combinations(4, 4).Shuffle(),
Combinations(4, 3).Shuffle(),
Combinations(4, 2).Shuffle(),
Combinations(4, 1).Shuffle()
}.MultiConcat().ToArray();
}
但现在我们可能会太简洁。
但现在不要停止。那里有很多重复的代码!
private bool[][] GetBoolArrays()
{
var q = from num in new[] { 4, 3, 2, 1 }
select Combinations(4, num).Shuffle();
return q.MultiConcat().ToArray();
}
哦等等,我们已经在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();
}
这就像我要做到的那样简洁。
请注意这里的课程:
答案 1 :(得分:2)
我假设您找到了一种方法来创建一个包含所需组合的数组。我们称之为allCombinations
。
您可以使用以下方法创建有序数组:
bool[][] orderedCombinations = allCombinations.OrderBy(combination => combination.Count(b => b)).ToArray();
这会根据包含的true
值的数量对组合进行排序。具有相同数量true
s的组合未排序(但未明确随机化)。
希望这有帮助。
更新要对具有相同数量的true
s的组合进行随机化,您可以尝试这样做:
Random rand = new Random();
bool[][] orderedCombinations = allCombinations.
OrderBy(combination => combination.Count(b => b)).
ThenBy(combination => rand.Next()).
ToArray();