Scroll through a list of characters

Asked

Viewed 4,494 times

3

I have a method that checks the number of characters in a string, and separates them into variables with the information as can be seen in this example.

The problem is when you have a list of data on string.

This data will always be separated with a count of 12 characters. Every 12 characters starts a new data in the string.

As in the example I use this string:

var exemplo = "13032015joao";

Got a way out:

13 
03 
2015 
joao

How to proceed when other data is in this string.

var exemplo = "13032015joao14032014Juca";

I need the way out:

13
03
2015
joao

14
03
2014
Juca

And repeating every time that string if it repeated.

  • @Marconi No. This string will change with each repeat. What I need is to separate this data every 12 characters.

2 answers

2


To separate the blocks. After separating the blocks you apply the separation of the individual fields as shown in your another question.

using System;
using static System.Console;
using System.Collections.Generic;
                    
public class Program {
    public static void Main() {
        var exemplo = "13032015joao14032015Juca23032015Joao24032015Jose";
        var partes = SplitBlocks(exemplo, 12);
        foreach(var parte in partes) WriteLine(parte);
        WriteLine();
        exemplo = "13032015joao14032015Juca23032015Joao24032015Jose1234";
        partes = SplitBlocksPartial(exemplo, 12);
        foreach(var parte in partes) {
            WriteLine(parte);
        }
    }
    public static List<String> SplitBlocks(string texto, int tamanho) {
        var partes = new List<String>();
        var posicao = 0;
        var total = texto.Length;
        while(total >= posicao + tamanho) {
            partes.Add(texto.Substring(posicao, tamanho));
            posicao += tamanho;
        }
        return partes;
    }
    public static List<String> SplitBlocksPartial(string texto, int tamanho) {
        var partes = new List<String>();
        var posicao = 0;
        var total = texto.Length;
        while(total >= posicao) {
            if (total >= posicao + tamanho) partes.Add(texto.Substring(posicao, tamanho));
            else partes.Add(texto.Substring(posicao));
            posicao += tamanho;
        }
        return partes;
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

I made an alternate version if there is a case where the block may not be complete and it should be picked up anyway. I don’t think you need it, but it’s there for whoever needs it.

Example joining the two solutions:

using System;
using static System.Console;
using System.Collections.Generic;
                    
public class Program {
    public static void Main() {
        var exemplo = "13032015joao14032015Juca23032015Joao24032015Jose";
        var blocos = SplitBlocks(exemplo, 12);
        foreach(var bloco in blocos) {
            var colunas = SplitFixed(bloco, new List<int>() { 2, 2, 4, 4});
            foreach(var coluna in colunas) WriteLine(coluna);
            WriteLine();
        }
    }
    public static List<String> SplitBlocks(string texto, int tamanho) {
        var partes = new List<String>();
        var posicao = 0;
        var total = texto.Length;
        while(total >= posicao + tamanho) {
            partes.Add(texto.Substring(posicao, tamanho));
            posicao += tamanho;
        }
        return partes;
    }
    public static List<String> SplitFixed(string texto, List<int> tamanhos) {
        var partes = new List<String>();
        var posicao = 0;
        foreach(var tamanho in tamanhos) {
            partes.Add(texto.Substring(posicao, tamanho));
            posicao += tamanho;
        }
        return partes;
    }
}

Behold working in the ideone. And in the .NET Fiddle. Also put on the Github for future reference.

You can make a method that already returns a list of lists with all parts already separated in a single algorithm. Eventually you could use a array instead of a list if there was a need but in general lists are preferable.

  • That’s exactly what it was, thanks for your help.

  • Debugging the code, I see that to each part, it adds one \r n before the new part. It would be possible to remove?

  • This makes no sense, nothing in the code indicates adding any extra character. It is likely that the text you are working on already has this. Then the problem is different from what you described.

  • I’m sorry. When reading the TXT file I was adding these characters to the end of each block and I hadn’t noticed.

1

There are several ways to do this, the idea is usually to go through the string and each n characters get block with method String.Substring() passing as parameter the initial position and the size of the current block, and finally adding it in a array.

The version using for of function SplitBlocks of maniero’s response:

static List<String> DividirBlocos(string texto, int blocos){
    var partes = new List<String>();
    int tamanho = texto.Length;
    // Incrementa "i" conforme o valor de "blocos". 0, 12, 24, 36...
    for (int i = 0; i < tamanho; i += blocos){
       if (i + blocos > tamanho) blocos = tamanho - i;
       partes.Add(texto.Substring(i, blocos));
    }
    return partes;
}

Functional example in Ideone.

Another alternative that can be used is through a query using LINQ:

static IEnumerable<string> DividirBlocos(string texto, double blocos){
    return Enumerable.Range(0, (int)Math.Ceiling(texto.Length / blocos)) 
       .Select(i => new string(texto
           .Skip(i * (int)blocos)
           .Take((int)blocos)
           .ToArray()));
}

Functional example in Ideone.

With the method Enumerable.Range a range of values, the Math.Ceiling is used to round up the result of the division between the text size and the amount of blocks, result that will be the amount of pieces obtained from the text.

On the next line is the .Select which is used to select each piece and apply an action on it, the .Skip is used to ignore a certain amount of characters and the .Take is used to recover certain amount of characters.

Note: It is necessary to include namespaces System.Collections.Generic and System.Linq.

Another way to do this can also be through regular expressions:

List<string> partes = new List<string>(Regex.Split(texto, @"(?<=\G.{12})",
RegexOptions.Multiline));

Functional example in Ideone.

Regular expressions in this case should probably be the most inefficient, in addition to lower performance.

To anchor \G is used to say that the match should start at the position where the previous match ended, the point (.) is used to capture any character, and finally, the {12} is used to delimit the amount of characters we want to return.

Note: It is necessary to include the namespace System.Text.RegularExpressions.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.