如何将由0和1组成的字符串转化为布尔数组

7
基本上,标题已经说了我想做什么。
我有一个字符串,如下所示。
1 0 1 0 1
0 0 0 0 0
1 0 0 0 1
0 0 0 0 0
1 0 1 0 1

我希望将其转换为一个二维布尔数组(显然,0表示false,1表示true)。我的当前方法是删除非换行空格,然后遍历字符串的每一行。
这使我需要将类似于10101的字符串转换为布尔数组true, false, true, false, true。现在,我希望有预先存在的方法来完成此转换 - 使用Java,我相信可以使用streams API来完成,但不幸的是,我还不熟练掌握C#。
因此,我的问题是:是否有现有的紧凑方式进行此转换?或者我必须手动遍历字符串并对每个字符执行== 0 / == 1比较?

那个“box”是一个单独的字符串(包含空格和换行符)吗?你想生成什么输出? - Amit
2
你认为是否存在将2D字符串盒子转换为2D布尔盒子的解决方案?我怀疑以前没有人这样做过,但我相信你自己可以做到。无论如何,这个问题要求提供库/文档,这在这里是不相关的话题。 - MakePeaceGreatAgain
@HimBromBeere 我希望它在标准库中,就像Java一样。 - PixelMaster
1
我很好奇,你指的是哪个Java方法?这似乎是一个非常特定的用例。 - Sinjai
你知道 LINQ 吗?它是一种标准的处理列表(包括字符串)的方式。 - Luis
显示剩余2条评论
5个回答

5

单个字符串

如果您有一个类似于“10101”的字符串,您可以使用LINQ将其转换为位数组。

string input = "10101";
bool[] flags = input.Select( c => c == '1' ).ToArray();

字符串数组

LINQ 不太适用于二维数组,但对锯齿状数组功能却十分强大。如果使用 bool[][] 可以满足需求,那么这个解决方案应该可以帮到你:

string[] input = { "10101","01010" };

bool[][] flags = input.Select
(
    s => s.Select
    ( 
        c => c == '1'
    )
    .ToArray()
)
.ToArray();

2
如果我没错的话,OP想要从原始“box”中得到一个二维布尔数组(即行和列)。 - Steve
@Steve 是的,但正如我在问题的倒数第二和倒数第三段提到的那样,我正在迭代字符串的行,然后可以使用这个解决方案。我想你也可以将整个过程作为一行完成,但我希望能够维护我的代码。 - PixelMaster
1
@PixelMaster,这不是你所请求的答案,对吧? ;) - Snazzie
@PixelMaster,如果有帮助的话,我的答案确实会返回一个bool[][] - Sinjai
1
编辑了答案,包括适用于字符串数组的示例。 - John Wu

4
这是一个相对丑陋的“一行代码”:
string input = "1 0 1 0 1\n0 0 0 0 0\n1 0 0 0 1\n0 0 0 0 0\n1 0 1 0 1";
bool[][] flags = input.Split(new[] { "\n" }, StringSplitOptions.None) // Split into lines, e.g. [ "1 0 1 0 1", "0 0 0 0 0" ]
                      .Select(line => line.Split(' ') // Split each line into array of "1"s or "0"s
                                          .Select(num => num == "1").ToArray()) // Project each line into boolean array
                      .ToArray(); // Get array of arrays

但这里有一个(可以说更易读的)版本,可能更接近我猜测的您实际使用情况,例如逐行从用户读取一行。

string input = "1 0 1 0 1\n0 0 0 0 0\n1 0 0 0 1\n0 0 0 0 0\n1 0 1 0 1";

List<bool[]> boolArrays = new List<bool[]>();

string[] lines = input.Split(new[] { "\n" }, StringSplitOptions.None);
foreach (string line in lines) // Could be a different loop that gets lines from the user, e.g. `do { var s = Console.ReadLine(); doMore(); } while (s != null);`
{
    string[] charsAsStrings = line.Split(' '); // TODO: Improve variable names
    bool[] arrayRow = charsAsStrings.Select(numString => numString == "1").ToArray(); // Parsing to int would be pointless
    boolArrays.Add(arrayRow);
}

bool[][] flags = list.ToArray();

正如评论中所述,通常应使用Environment.NewLine而不是"\n"。请注意,我们无法仅通过提供整个数组来拆分字符串--但可以通过扩展方法解决这个问题。

第一个方案不错。你也可以考虑使用 Environment.Newline 来分隔行。 - Jimi
@Jimi | 确实如此,我经常这样做——主要是因为我认为这样更容易阅读。我想,没有必要这样做,因为我非常怀疑 OP 实际上会声明一个多行的逐字字符串。第二种方法有什么问题吗? - Sinjai
据我所知,第二个版本中的所有步骤仍然在第一个版本中完成,只是不那么明显。 - Sinjai
这就是我说“冗余”的原因 :) 无论如何,Linq方法可以被缓存,由于此功能性能将大大提高。列表转换则不行。 - Jimi
@PixelMaster 对,我也是这么想的。但是你确实问了关于二维数组的问题,所以我先回答了你明确的问题。第二种方法,就像我的答案说的那样,可能更接近于你实际使用的情况。 - Sinjai
显示剩余3条评论

2

与@Sinjai的答案类似。通过利用一个字符串可以作为char[]进行.Select的事实,这种方法是有效的。

var boolVals = yourString.Replace(" ","").Replace("\r","")
    .Split('\n').Select(x => x.Select(y => y == '1').ToArray()).ToArray();

这个方法适用于有或没有\r\n和空格的情况。如果你有一个像下面这样的字符串:

string yourString = "10101\n10001";

那么代码就会更短:

var boolVals = yourString.Split('\n').Select(x => x.Select(y => y == '1').ToArray()).ToArray();

我很好奇,如果按照 Environment.NewLine 进行分割,是否就不需要替换 \r 出现的情况了? - Sinjai
如果您知道您始终拥有环境的换行符,那么您可以这样做。但是,这也意味着您需要使用使用string[]StringSplitOptions的split重载。我喜欢这个版本,因为它可以在有或没有\r以及有或没有空格的情况下工作。 - aquinas
明白了。这可能是避免使用 var 的时候,对吧?考虑到正在进行的大量链接的 Select - Sinjai

0

尝试使用这个函数:

static List<bool> AsArray(string boolString)
{
    List<bool> toArray = new List<bool>();
    foreach (char boolChar in boolString)
    {
        if (boolChar == '0')
        {
            toArray.Add(false);
        }
        else if (boolChar == '1')
        {
            toArray.Add(true);
        }
        else
        {
            throw new Exception("String can only be made of 1 and 0.");
        }
    }
    return toArray;
}

OP 要求的是 2D 布尔数组,而不是列表。 - Snazzie
LINQ是更好、更短、更容易的解决方案。 - Luis

-1
以下是以一个5x5的布尔数组为例实现你所需求的代码。

代码

        string str = "1 0 1 0 1 " +
                     "0 0 0 0 1 " +
                     "0 1 1 1 0 " +
                     "1 0 1 0 1 " +
                     "1 1 1 1 1";

        string[] stringArray = str.Split(' '); // split strings into string array using "space" as split
        bool[,] boolArray = new bool[5, 5];

        int counter = 0;  // counter for iterating through stringArray
        int counterMax = stringArray.Length - 1; // set max for counter to stop index out of range


        for (int j = 0; j < 5; j++) // Y axis
        {
            for (int i = 0; i < 5; i++) // X axis
            {
                if (stringArray[counter] == "0")
                {
                    boolArray[j, i] = false;
                }
                else
                {
                    boolArray[j, i] = true;
                }
                if (counter < counterMax)
                {
                    counter++;
                }
                else
                {
                    break;
                }

            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接