C# - Split Array by Another Array

Viewed 218

I have a string array and I want to split by another array(by each item from second array).

string[] array1 = { "item1", "item2", "item3", "item4", "item5" ,"item6" };
string[] array2 = { "item2", "item5" };

results in string[][] or List<string[]>

results[0] = { "item1" }  
results[1] = { "item2", "item3", "item4" }  
results[2] = { "item5", "item6" }

Also item which split should added before next array. eg. item2 splited results[0] and results[1] and and used in front of result[1].
Hints: It might be something like using IndexOf() or Insert() in for loop function

I have tried this with string. but I don't know how to proceed with array.

string str = "item1,item2,item3,item4,item5,item6";
string[] array = str.Split(new string[] { "item2","item5" }, StringSplitOptions.None);

I tried find this question in google but so far nothing found. Only thing I found how split in chuncks(meaning number of items in each array) but not by another item(multiple items Especially).

1 Answers

So you want a "split-on" method, which splits one collection into multiple by providing the split-index in a second collection? You could use following extension method which uses a Queue<T>(FIFO) for the split-on items. It's pretty flexible, you can use it with every type and you can optionally provide the comparer. If you for example wanted to compare in a case-insensitive manner provide StringComparer.CurrentCultureIgnoreCase:

public static class EnumerableExtensions
{
   public static IList<IList<T>> SplitOnItems<T>(this IEnumerable<T> seqeuenceToSplit, IEnumerable<T> splitOnItems, IEqualityComparer<T> comparer = null)
   {    
        if(comparer == null) comparer = EqualityComparer<T>.Default;
        Queue<T> queue = new Queue<T>(splitOnItems);
        if(queue.Count == 0)
        {
            return new IList<T>[]{new List<T>(seqeuenceToSplit)};
        }

        T nextSplitOnItem = queue.Dequeue();
        List<T> nextBatch = new List<T>();
        IList<IList<T>> resultList = new List<IList<T>>();
        bool takeRemaining = false;
        foreach(T item in seqeuenceToSplit)
        {
            if(!takeRemaining && comparer.Equals(item, nextSplitOnItem))
            {
                resultList.Add(nextBatch);
                nextBatch = new List<T> { item };
                if (queue.Count > 0)
                {
                    nextSplitOnItem = queue.Dequeue();
                }
                else
                {
                    takeRemaining = true;
                }
            }
            else
            {
                nextBatch.Add(item);
            }
        }
        if(nextBatch.Any()) 
            resultList.Add(nextBatch);

        return resultList;
   }
}

Usage:

string[] array1 = { "item1", "item2", "item3", "item4", "item5" ,"item6" };
string[] array2 = { "item2", "item5" };
IList<IList<string>> splittedItems = array1.SplitOnItems(array2);
Related