读取一个字符串,一次 3x3 个字符

发布于 2024-12-01 18:15:37 字数 637 浏览 0 评论 0原文

所以想象一下这个字符串:

    _  _     _  _  _  _  _
  | _| _||_||_ |_   ||_||_|
  ||_  _|  | _||_|  ||_| _| 

分割这个字符串以便每个数字都可以由它自己处理的最简单/最好的方法是什么?

我正在考虑类似

public string[] SplitIntoNumbers(string input)

结果的事情,有

["     |  |", " _  _||_ ", " _  _| _|", ...]

什么想法吗?

编辑
对于那些想要更多信息的人 - 问题来自 BankOCR-kata CodingDojo。我意识到有多种“只是完成工作”的方法——解决方案,但我觉得必须有一种更“奇特”的方法来解决它。类似于 clojure 的东西。

So imagine this string:

    _  _     _  _  _  _  _
  | _| _||_||_ |_   ||_||_|
  ||_  _|  | _||_|  ||_| _| 

What would be the easiest / nicest way of splitting this string so that each number could be handled by it self?

I'm thinking of something like

public string[] SplitIntoNumbers(string input)

where the result would be like

["     |  |", " _  _||_ ", " _  _| _|", ...]

Any ideas?

Edit
For thous wanting some more information - The problem comes from the BankOCR-kata over at CodingDojo. I realize that there are multiple ways of 'just get the job done'-solutions, but I felt that there had to be a more 'fancy' way of solving it. Something clojure-alike.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

玉环 2024-12-08 18:15:37

你问:

<块引用>

分割该字符串以便每个数字都可以自行处理的最简单/最好的方法是什么?

...我认为您可能过于从面向对象的角度来处理这个问题。你所说的实际上是一种“字体”,而不是字符的集合。坦率地说,我只是将逻辑包装到一个类中,并完全按照您在这篇文章中所做的那样定义字符数据。它易于查看、编辑和维护。

从您原来的帖子中我不明白您的最终目标是否只是渲染,或者是否是解析。无论如何,我不能只停留在数字上;)

    static void Main()
    {
        LineBuffers lb = new LineBuffers(80 / 3);
        lb.Write(0, "-_ 1234567890");
        Console.WriteLine(String.Join(Environment.NewLine, lb.Lines.ToArray()));
        Console.WriteLine();
        Console.WriteLine(lb.ReadLine());

        lb.Clear();
        lb.Write(0, "abcdefghijklm");
        Console.WriteLine(String.Join(Environment.NewLine, lb.Lines.ToArray()));
        Console.WriteLine();
        Console.WriteLine(lb.ReadLine());

        lb.Clear();
        lb.Write(0, "nopqrstuvwxyz");
        Console.WriteLine(String.Join(Environment.NewLine, lb.Lines.ToArray()));
        Console.WriteLine();
        Console.WriteLine(lb.ReadLine());

        lb = new LineBuffers(" _     _  _  _ ", "|_| _ |  |_ |_|", @"|\ |_||_-|_ |\ ");
        Console.WriteLine(lb.ReadLine());

    }

    public class LineBuffers
    {
        private static string Characters = " -0123456789_abcdefghijklmnopqrstuvwxyz";
        private static readonly string[] Format =
            (
            @".   .   . _ .   . _ . _ .   . _ . _ . _ . _ . _ .   . _ .   . _ .   . _ . _ . _ .   . _ .  _.   .   .   .   .   . _ . _ . _ . _ .___.   .   .   .   .   .__ ." + "\n" +
            @".   . _ .| |.  |. _|. _|.|_|.|_ .|_ .  |.|_|.|_|.   .|_|.|_ .|  . _|.|_ .|_ .|  .|_|. | .  |.|/ .|  .|\|.|\|. _ .|_|.|_|.|_|./_ . | .| |.| |.|||. \/. \/. / ." + "\n" +
            @".   .   .|_|.  |.|_ . _|.  |. _|.|_|.  |.|_|. _|.___.| |.|_|.|_ .|_|.|_ .|  .|_-.| |. | . _|.|\ .|_ .|||.| |.|_|.|  .  |.|\ . _/. | .|_|.|/ .|/|. /\. | ./_ ."
            ).Split('\n');

        private readonly char[][] _lines;

        public LineBuffers(int charWidth)
        {
            _lines = new char[3][] {new char[charWidth*3], new char[charWidth*3], new char[charWidth*3]};
            Clear();
        }

        public LineBuffers(string line1, string line2, string line3) 
            : this(line1.ToCharArray(), line2.ToCharArray(), line3.ToCharArray()) { }

        public LineBuffers(char[] line1, char[] line2, char[] line3)
        {
            if (line1 == null || line2 == null || line3 == null 
                || line1.Length != line2.Length || line2.Length != line3.Length)
                throw new ArgumentException();

            _lines = new char[3][] {
                line1, line2, line3
            };
        }

        public int Count { get { return _lines[0].Length / 3; } }
        public IEnumerable<string> Lines { get { return _lines.Select(chars => new String(chars)); } }

        public void Clear()
        {
            for (int i = 0; i < Count; i++)
                Write(i, ' ');
        }

        public void Write(int position, IEnumerable<Char> character)
        { foreach (char ch in character) Write(position++, ch); }

        public void Write(int position, Char character)
        {
            int charIx = Characters.IndexOf(Char.ToLower(character));
            if (charIx < 0)
                throw new ArgumentOutOfRangeException("character");
            if (position >= Count)
                throw new ArgumentOutOfRangeException("position");

            int offset = charIx*4 + 1;
            for(int line=0; line <3; line++)
                Array.Copy(Format[line].ToCharArray(offset, 3), 0, _lines[line], position * 3, 3);
        }

        public Char Read(int position)
        {
            if (position >= Count)
                throw new ArgumentOutOfRangeException("position");

            IEnumerable<int> found = Find(Format[0], _lines[0], position*3)
                .Intersect(Find(Format[1], _lines[1], position*3))
                .Intersect(Find(Format[2], _lines[2], position*3));

            int[] result = found.ToArray();
            if (result.Length != 1)
                throw new FormatException();
            return Characters[result[0]];
        }

        IEnumerable<int> Find(string findIn, char[] text, int charIx)
        {
            for(int i=1; i < findIn.Length; i += 4)
            {
                if (findIn[i] == text[charIx] && findIn[i + 1] == text[charIx + 1] && findIn[i + 2] == text[charIx + 2])
                    yield return i/4;
            }
        }

        public string ReadLine()
        {
            char[] text = new char[Count];
            for (int ix = 0; ix < Count; ix++)
                text[ix] = Read(ix);
            return new String(text);
        }
    }

前面的程序输出以下文本:

             _  _     _  _  _  _  _  _
 _         | _| _||_||_ |_   ||_||_|| |
   ___     ||_  _|  | _||_|  ||_| _||_|

-_ 1234567890
 _     _     _  _  _     _   _
|_||_ |   _||_ |_ |  |_| |   ||/ |  |\|
| ||_||_ |_||_ |  |_-| | |  _||\ |_ |||

abcdefghijklm
       _  _  _  _ ___               __
|\| _ |_||_||_|/_  | | || |||| \/ \/ /
| ||_||    ||\  _/ | |_||/ |/| /\ | /_

nopqrstuvwxyz

You asked:

What would be the easiest / nicest way of splitting this string so that each number could be handled by it self?

... I think you may be approaching this from a little too much of an OO perspective. What your talking about is really a 'font' more than it is a collection of characters. I would frankly just wrap up the logic into a single class and define the character data exactly as you did for this post. It's easy to see, edit, and maintain.

I didn't understand from your original post if your ultimate goal was just rendering, or if it was parsing. Anyway I couldn't just stop at only numbers ;)

    static void Main()
    {
        LineBuffers lb = new LineBuffers(80 / 3);
        lb.Write(0, "-_ 1234567890");
        Console.WriteLine(String.Join(Environment.NewLine, lb.Lines.ToArray()));
        Console.WriteLine();
        Console.WriteLine(lb.ReadLine());

        lb.Clear();
        lb.Write(0, "abcdefghijklm");
        Console.WriteLine(String.Join(Environment.NewLine, lb.Lines.ToArray()));
        Console.WriteLine();
        Console.WriteLine(lb.ReadLine());

        lb.Clear();
        lb.Write(0, "nopqrstuvwxyz");
        Console.WriteLine(String.Join(Environment.NewLine, lb.Lines.ToArray()));
        Console.WriteLine();
        Console.WriteLine(lb.ReadLine());

        lb = new LineBuffers(" _     _  _  _ ", "|_| _ |  |_ |_|", @"|\ |_||_-|_ |\ ");
        Console.WriteLine(lb.ReadLine());

    }

    public class LineBuffers
    {
        private static string Characters = " -0123456789_abcdefghijklmnopqrstuvwxyz";
        private static readonly string[] Format =
            (
            @".   .   . _ .   . _ . _ .   . _ . _ . _ . _ . _ .   . _ .   . _ .   . _ . _ . _ .   . _ .  _.   .   .   .   .   . _ . _ . _ . _ .___.   .   .   .   .   .__ ." + "\n" +
            @".   . _ .| |.  |. _|. _|.|_|.|_ .|_ .  |.|_|.|_|.   .|_|.|_ .|  . _|.|_ .|_ .|  .|_|. | .  |.|/ .|  .|\|.|\|. _ .|_|.|_|.|_|./_ . | .| |.| |.|||. \/. \/. / ." + "\n" +
            @".   .   .|_|.  |.|_ . _|.  |. _|.|_|.  |.|_|. _|.___.| |.|_|.|_ .|_|.|_ .|  .|_-.| |. | . _|.|\ .|_ .|||.| |.|_|.|  .  |.|\ . _/. | .|_|.|/ .|/|. /\. | ./_ ."
            ).Split('\n');

        private readonly char[][] _lines;

        public LineBuffers(int charWidth)
        {
            _lines = new char[3][] {new char[charWidth*3], new char[charWidth*3], new char[charWidth*3]};
            Clear();
        }

        public LineBuffers(string line1, string line2, string line3) 
            : this(line1.ToCharArray(), line2.ToCharArray(), line3.ToCharArray()) { }

        public LineBuffers(char[] line1, char[] line2, char[] line3)
        {
            if (line1 == null || line2 == null || line3 == null 
                || line1.Length != line2.Length || line2.Length != line3.Length)
                throw new ArgumentException();

            _lines = new char[3][] {
                line1, line2, line3
            };
        }

        public int Count { get { return _lines[0].Length / 3; } }
        public IEnumerable<string> Lines { get { return _lines.Select(chars => new String(chars)); } }

        public void Clear()
        {
            for (int i = 0; i < Count; i++)
                Write(i, ' ');
        }

        public void Write(int position, IEnumerable<Char> character)
        { foreach (char ch in character) Write(position++, ch); }

        public void Write(int position, Char character)
        {
            int charIx = Characters.IndexOf(Char.ToLower(character));
            if (charIx < 0)
                throw new ArgumentOutOfRangeException("character");
            if (position >= Count)
                throw new ArgumentOutOfRangeException("position");

            int offset = charIx*4 + 1;
            for(int line=0; line <3; line++)
                Array.Copy(Format[line].ToCharArray(offset, 3), 0, _lines[line], position * 3, 3);
        }

        public Char Read(int position)
        {
            if (position >= Count)
                throw new ArgumentOutOfRangeException("position");

            IEnumerable<int> found = Find(Format[0], _lines[0], position*3)
                .Intersect(Find(Format[1], _lines[1], position*3))
                .Intersect(Find(Format[2], _lines[2], position*3));

            int[] result = found.ToArray();
            if (result.Length != 1)
                throw new FormatException();
            return Characters[result[0]];
        }

        IEnumerable<int> Find(string findIn, char[] text, int charIx)
        {
            for(int i=1; i < findIn.Length; i += 4)
            {
                if (findIn[i] == text[charIx] && findIn[i + 1] == text[charIx + 1] && findIn[i + 2] == text[charIx + 2])
                    yield return i/4;
            }
        }

        public string ReadLine()
        {
            char[] text = new char[Count];
            for (int ix = 0; ix < Count; ix++)
                text[ix] = Read(ix);
            return new String(text);
        }
    }

The preceeding program outputs the following text:

             _  _     _  _  _  _  _  _
 _         | _| _||_||_ |_   ||_||_|| |
   ___     ||_  _|  | _||_|  ||_| _||_|

-_ 1234567890
 _     _     _  _  _     _   _
|_||_ |   _||_ |_ |  |_| |   ||/ |  |\|
| ||_||_ |_||_ |  |_-| | |  _||\ |_ |||

abcdefghijklm
       _  _  _  _ ___               __
|\| _ |_||_||_|/_  | | || |||| \/ \/ /
| ||_||    ||\  _/ | |_||/ |/| /\ | /_

nopqrstuvwxyz
淡紫姑娘! 2024-12-08 18:15:37

开门见山:

    public static string[] SplitIntoNumbers(string input)
    {
        List<string> result = new List<string>();
        string[] subStrs = input.Split(new char[] { '\r', '\n' }, 3, StringSplitOptions.RemoveEmptyEntries);
        for (int it = 0; it < subStrs[0].Length; it += 3)
        {
            result.Add(subStrs[0].Substring(it, 3)
                + subStrs[1].Substring(it, 3)
                + subStrs[2].Substring(it, 3));
        }
        return result.ToArray();
    }

(编辑) 我使用的字符串是这样的:

    static string str =
@"
    _  _     _  _  _  _  _ 
  | _| _||_||_ |_   ||_||_|
  ||_  _|  | _||_|  ||_| _|";

Straight to the point:

    public static string[] SplitIntoNumbers(string input)
    {
        List<string> result = new List<string>();
        string[] subStrs = input.Split(new char[] { '\r', '\n' }, 3, StringSplitOptions.RemoveEmptyEntries);
        for (int it = 0; it < subStrs[0].Length; it += 3)
        {
            result.Add(subStrs[0].Substring(it, 3)
                + subStrs[1].Substring(it, 3)
                + subStrs[2].Substring(it, 3));
        }
        return result.ToArray();
    }

(EDIT) The string I used was this:

    static string str =
@"
    _  _     _  _  _  _  _ 
  | _| _||_||_ |_   ||_||_|
  ||_  _|  | _||_|  ||_| _|";
墨离汐 2024-12-08 18:15:37

我将使用正则表达式来构建具有与此类似的模式的匹配列表,

(.{3})

这会将输入分解为 3x1 匹配的块,并根据您拥有的匹配数量来确定数字。例如,

    _  _     _  _  _  _  _
  | _| _||_||_ |_   ||_||_|
  ||_  _|  | _||_|  ||_| _| 

将生成 27 个 3x1 段的匹配,并且由于每个数字有 3 行高,因此您可以只取 27 / 3 = 9 个单独的数字。然后,您只需循环遍历正则表达式匹配并将它们组合到您想要的输出中。

void Main()
{
    string input = "    _  _     _  _  _  _  _ \r\n  | _| _||_||_ |_   ||_||_|\r\n  ||_  _|  | _||_|  ||_| _|";

    string[] result = SplitIntoNumbers(input);
}

public string[] SplitIntoNumbers(string input)
{
    List<string> results = new List<string>();

    Regex rx = new Regex("(.{3})");
    MatchCollection matches = rx.Matches(input);
    int totalNumbers = matches.Count / 3;

    for(int i = 0; i < totalNumbers; i++)
    {
        string s = string.Concat(matches[i].Value, matches[i + totalNumbers].Value, matches[i + (totalNumbers * 2)].Value);

        results.Add(s);
    }

    return results.ToArray();
}

I would use regex to build up a list of matches with a pattern similar to this

(.{3})

this would break the input into chunks of 3x1 matches, and depending on how many matches you have would determine the numbers. For example

    _  _     _  _  _  _  _
  | _| _||_||_ |_   ||_||_|
  ||_  _|  | _||_|  ||_| _| 

would generate 27 matches of 3x1 segments, and since each number is 3 lines high you can just take the 27 / 3 = 9 separate numbers. Then you would just have to loop through the regex matches and combine them into the output that you want.

void Main()
{
    string input = "    _  _     _  _  _  _  _ \r\n  | _| _||_||_ |_   ||_||_|\r\n  ||_  _|  | _||_|  ||_| _|";

    string[] result = SplitIntoNumbers(input);
}

public string[] SplitIntoNumbers(string input)
{
    List<string> results = new List<string>();

    Regex rx = new Regex("(.{3})");
    MatchCollection matches = rx.Matches(input);
    int totalNumbers = matches.Count / 3;

    for(int i = 0; i < totalNumbers; i++)
    {
        string s = string.Concat(matches[i].Value, matches[i + totalNumbers].Value, matches[i + (totalNumbers * 2)].Value);

        results.Add(s);
    }

    return results.ToArray();
}
难以启齿的温柔 2024-12-08 18:15:37

假设您想要保留字符串数组用于输入,我们可以非常简单地循环遍历一次拉 3 个字符的行。

    var numbers = new[]
                    {
                        "    _  _     _  _  _  _  _ ",
                        "  | _| _||_||_ |_   ||_||_|",
                        "  ||_  _|  | _||_|  ||_| _|"
                    };

            // just in case length is off on one, don't want to crash
    var length = numbers.Min(line => line.Length);
    var results = new List<string>();

            // go by groups of three
    for (int i = 0; i < length; i += 3)
    {
        var builder = new StringBuilder();
        for (int j = 0; j < numbers.Length; j++)
        {
            builder.Append(numbers[j].Substring(i, 3));
        }

        results.Add(builder.ToString());
    }

            // print the results
    foreach (var digit in results)
    {
        Console.WriteLine(digit);
    }

Assuming you want to keep the array of strings for input, we could loop very simply through the lines pulling 3 chars at a time.

    var numbers = new[]
                    {
                        "    _  _     _  _  _  _  _ ",
                        "  | _| _||_||_ |_   ||_||_|",
                        "  ||_  _|  | _||_|  ||_| _|"
                    };

            // just in case length is off on one, don't want to crash
    var length = numbers.Min(line => line.Length);
    var results = new List<string>();

            // go by groups of three
    for (int i = 0; i < length; i += 3)
    {
        var builder = new StringBuilder();
        for (int j = 0; j < numbers.Length; j++)
        {
            builder.Append(numbers[j].Substring(i, 3));
        }

        results.Add(builder.ToString());
    }

            // print the results
    foreach (var digit in results)
    {
        Console.WriteLine(digit);
    }
々眼睛长脚气 2024-12-08 18:15:37

扩展方法怎么样:

    public static string[] SplitIntoNumbers(this string str)
    {
        var lines = str.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        var columns = lines
            .Select(x => x.InSetsOf(3).Select(y => new string(y.ToArray())).ToList())
            .ToList();
        var numbers = Enumerable.Range(0, columns[0].Count)
            .Select(x => columns[0][x] + columns[1][x] + columns[2][x])
            .ToArray();
        return numbers;
    }

假设InSetsOf()的兼容实现可用。

用法:

        var result = input.SplitIntoNumbers();

How about an extension method:

    public static string[] SplitIntoNumbers(this string str)
    {
        var lines = str.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
        var columns = lines
            .Select(x => x.InSetsOf(3).Select(y => new string(y.ToArray())).ToList())
            .ToList();
        var numbers = Enumerable.Range(0, columns[0].Count)
            .Select(x => columns[0][x] + columns[1][x] + columns[2][x])
            .ToArray();
        return numbers;
    }

assuming a compatible implementation of InSetsOf() is available.

usage:

        var result = input.SplitIntoNumbers();
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文