1

so I was solving some unrelated coding challenge and I needed to split an int array based on an element.

similar to how String.Split works.

for example:

var arr1 = new int [] { 3, 3, 0, 2, 4, 3, 2 };
var arr2 = new int [] { 8, 8, 5, 7, 9, 8, 7, 4, 8 };
var results1 = Split(arr1, 0);
foreach (var arr in results1)
    Console.WriteLine(string.Join(",", arr));
var results2 = Split(arr2, 8);
foreach (var arr in results2)
    Console.WriteLine(string.Join(",", arr));

the output here is:

3,3

2,4,3,2

5,7,9

7,4

I was surprised, I could not find any answers for this, String.Split kept coming up, but no integer!

so I wrote this:

public int[][] Split(int[] arr, int element)
{
    List<int[]> arrays = new List<int[]>();
    int skip = 0;
    int take = 0;
    for (int i = 0; i < arr.Length; i++)
    {
        if (arr[i] == element && take != 0)
        {
            arrays.Add(arr.Skip(skip).Take(take).ToArray());
            skip = i + 1;
            take = 0;
            continue;
        }

        if (arr[i] != element)
            take++;

        if (take == 0)
            skip = i + 1;

        if (arr.Length - 1 == i && take != 0)
            arrays.Add(arr.Skip(skip).Take(take).ToArray());
     }

     return arrays.ToArray();
 }

this works (I think), but it is very messy and I don't like it

Any other solutions?

2 Answers 2

4

In general case, you can implement it (String.Split like routine but for IEnumerable<T>) as follows:

public static IEnumerable<T[]> Split<T>(IEnumerable<T> source, 
                                        T delimiter, 
                                        StringSplitOptions options = StringSplitOptions.None,
                                        IEqualityComparer<T> comparer = null) {
  if (null == source)
    yield break; // Or throw new ArgumentNullException(nameof(source));

  if (null == comparer)
    comparer = EqualityComparer<T>.Default;
  
  List<T> current = new List<T>();

  foreach (T item in source) {
    if (comparer.Equals(item, delimiter)) {
      if (current.Count > 0 || !options.HasFlag(StringSplitOptions.RemoveEmptyEntries))
        yield return current.ToArray();

      current.Clear();
    }
    else
      current.Add(item);
  }

  if (current.Count > 0 || !options.HasFlag(StringSplitOptions.RemoveEmptyEntries))
    yield return current.ToArray();
}     

Then

var arr1 = new int [] { 3, 3, 0, 2, 4, 3, 2 };
var results1 = Split(arr1, 0);

foreach (var arr in results1)
  Console.WriteLine(string.Join(", ", arr));
Sign up to request clarification or add additional context in comments.

Comments

1
    public static IEnumerable<List<TValue>> SplitBy<TValue>(List<TValue> source, TValue by)
        {
            int start = 0;
            int count = 0;
            foreach (TValue item in source)
            {
                if (item.Equals(by))
                {
                    List<TValue> part = source.GetRange(start, count);
                    start = start + count + 1;
                    count = 0;
                    if (part.Any())
                    {
                        yield return part;
                    }
                }
                else
                {
                    count++;
                }
                
            }
            
            List<TValue> rest = source.GetRange(start, count);
            yield return rest;
        }

https://dotnetfiddle.net/Widget/Preview?url=/Widget/7ORu8p

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.