Go through a list of characters

3

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

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

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

As in the example I use this string :

var exemplo = "13032015joao";

I have the output:

13 
03 
2015 
joao

How to proceed when other data exists in this string .

var exemplo = "13032015joao14032014Juca";

I need the output to be:

13
03
2015
joao

14
03
2014
Juca

And repeating every time this string was repeated.

    
asked by anonymous 13.03.2015 / 18:15

2 answers

2

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

using System;
using 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;
    }
}

See working on dotNetFiddle .

I made an alternate version if a case occurs where the block may not be complete and it should be picked up anyway. I think you do not need it, but it's there for those who need it.

Example joining the two solutions:

using System;
using 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;
    }
}

See working on dotNetFiddle .

You can do a method that already returns a list of lists with all parts already separated into a single algorithm. You could eventually use an array instead of a list if there was a need but generally lists are preferable.

    
13.03.2015 / 18:19
1

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

The version using for of the SplitBlocks function of bigown answer :

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 on 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 on Ideone .

With the method Enumerable.Range you get 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 in>, this result being the quantity of pieces obtained from the text.

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

Note : You must include the 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.

The anchor \G is used to say that the match should begin at the position where the previous match ended, the dot ( . ) is used to catch any character, and finally, the {12} is used to delimit the amount of characters we want to return. >

Note : You must include the namespace System.Text.RegularExpressions .

    
14.03.2015 / 00:20