2

Problem

Given a sample string abcdef, i am trying to split that into an array of two character string elements that should results in ['ab','cd','ef'];

What i tried

I tried to iterate through the string while storing the substring in the current index in an array i declared inside the method, but am getting this output ['ab','bc','cd','de','ef']

Code I used

static string[] mymethod(string str)
{
    string[] r= new string[str.Length];
    for(int i=0; i<str.Length-1; i++)
    {
        r[i]=str.Substring(i,2);
    }
    return r;
}

Any solution to correct that with the code to return the correct output is really welcome, Thanks

12
  • 3
    In your solution, i doesn't look to be moving with the same length of the substring.. Always incrementing by 1 instead of by 2 (what you're wanting to be the 'cutoff' point per grouping) Commented Sep 22, 2021 at 12:31
  • @Mark. C, okay changing the increment variable in the code, will be back with feedback Commented Sep 22, 2021 at 12:36
  • 1
    You do realize that half your "r" array will be empty in your requested output? Commented Sep 22, 2021 at 12:36
  • @Hans Kestling, i mplemented the corrections as suggested and th code is working fine Commented Sep 22, 2021 at 12:38
  • stackoverflow.com/questions/1450774/… Commented Sep 22, 2021 at 12:41

5 Answers 5

4

your problem was that you incremented your index by 1 instead of 2 every time

 var res = new List<string>();
 for (int i = 0; i < x.Length - 1; i += 2)
 {
     res.Add(x.Substring(i, 2));
 }

should work

EDIT: because you ask for a default _ suffix in case of odd characters amount, this should be the change:

  var testString = "odd";
  string workOn = testString.Length % 2 != 0
     ? testString + "_"
     : testString;
  var res = new List<string>();
  for (int i = 0; i < workOn.Length - 1; i += 2)
  {
      res.Add(workOn.Substring(i, 2));
  }

two notes to notice:

  • in .NET 6 Chunk() is available so you can use this as suggested in other answers
  • this solution might not be the best in case of a very long input so it really depends on what are your inputs and expectations
Sign up to request clarification or add additional context in comments.

5 Comments

r should be half the length of the original string (because each index contains 2 characters). This will also throw an exception for odd string lengths.
@JohnathanBarclay, the input is having an array of two characters,
@JohnathanBarclay, did you run it? it would not thrown nothing dotnetfiddle.net/YBhzZ1
OK, it drops the last character rather than throwing an exception.
right, as the last character cannot be assigned with another character to compound a two character string as requested @JohnathanBarclay
3

.net 6 has an IEnumerable.Chunk() method that you can use to do this, as follows:

public static void Main()
{
    string[] result = 
       "abcdef"
       .Chunk(2)
       .Select(chunk => new string(chunk)).ToArray();

    Console.WriteLine(string.Join(", ", result)); // Prints "ab, cd, ef"
}

Before .net 6, you can use MoreLinq.Batch() to do the same thing.


[EDIT] In response the the request below:

MoreLinq is a set of Linq utilities originally written by Jon Skeet. You can find an implementation by going to Project | Manage NuGet Packages and then browsing for MoreLinq and installing it.

After installing it, add using MoreLinq.Extensions; and then you'll be able to use the MoreLinq.Batch extension like so:

public static void Main()
{
    string[] result = "abcdef"
       .Batch(2)
       .Select(chunk => new string(chunk.ToArray())).ToArray();

    Console.WriteLine(string.Join(", ", result)); // Prints "ab, cd, ef"
}

Note that there is no string constructor that accepts an IEnumerable<char>, hence the need for the chunk.ToArray() above.

I would say, though, that including the whole of MoreLinq just for one extension method is perhaps overkill. You could just write your own extension method for Enumerable.Chunk():

public static class MyBatch
{
    public static IEnumerable<T[]> Chunk<T>(this IEnumerable<T> self, int size)
    {
        T[] bucket = null;
        int count  = 0;

        foreach (var item in self)
        {
            if (bucket == null)
                bucket = new T[size];

            bucket[count++] = item;

            if (count != size)
                continue;

            yield return bucket;

            bucket = null;
            count  = 0;
        }

        if (bucket != null && count > 0)
            yield return bucket.Take(count).ToArray();
    }
}

2 Comments

Can you elaborate more on then MoreLinq.Batch() because i happen not to have that version of C#
morelinq isn't part of the .Net Framework, but an additionnal, open source, library you can use in your projects
3

If you are using latest .NET version i.e (.NET 6.0 RC 1), then you can try Chunk() method,

var strChunks = "abcdef".Chunk(2); //[['a', 'b'], ['c', 'd'], ['e', 'f']]

var result = strChunks.Select(x => string.Join('', x)).ToArray(); //["ab", "cd", "ef"]

Note: I am unable to test this on fiddle or my local machine due to latest version of .NET

9 Comments

Can someone point me any C# fiddle which supports 6.0 RC 1 C# version
Note that ToCharArray is unnecessary, as string implements IEnumerable<char> anyway.
@PrasadTelkikar, unfortunately there isn't any at the moment
Quite simple and fast, i like solutions that use minimal code to achieve goal
Ah darn, I was too slow :) Good answer.
|
0

With linq you can achieve it with the following way:

char[] word = "abcdefg".ToCharArray();
var evenCharacters = word.Where((_, idx) => idx % 2 == 0);
var oddCharacters = word.Where((_, idx) => idx % 2 == 1);
var twoCharacterLongSplits = evenCharacters
    .Zip(oddCharacters)
    .Select((pair) => new char[] { pair.First, pair.Second });

The trick is the following, we create two collections:

  • one where we have only those characters where the original index was even (% 2 == 0)
  • one where we have only those characters where the original index was odd (% 2 == 1)

Then we zip them. So, we create a tuple by taking one item from the even and one item from the odd collection. Then we create a new tuple by taking one item from the even and ...

And last we convert the tuples to arrays to have the desired output format.

Comments

0

You are on the right track but you need to increment by 2 not by one. You also need to check if the array has not ended before taking the second character else you risk running into an index out of bounds exception. Try this code I've written below. I've tried it and it works. Best!

public static List<string> splitstring(string str)
        {
            List<string> result = new List<string>();
            int strlen = str.Length;
            for(int i = 0; i<strlen; i+=2)
            {
                string currentstr = str[i].ToString();
                if (i + 1 <= strlen-1)
                { currentstr += str[i + 1].ToString(); }
                result.Add(currentstr);
            }
            return result;
        }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.