Splitting a string into chunks of a certain size

后端 未结 30 2043
时光说笑
时光说笑 2020-11-22 07:55

Suppose I had a string:

string str = \"1111222233334444\"; 

How can I break this string into chunks of some size?

e.g., breaking t

30条回答
  •  故里飘歌
    2020-11-22 08:20

    I can't remember who gave me this, but it works great. I speed tested a number of ways to break Enumerable types into groups. The usage would just be like this...

    List Divided = Source3.Chunk(24).Select(Piece => string.Concat(Piece)).ToList();
    

    The extention code would look like this...

    #region Chunk Logic
    private class ChunkedEnumerable : IEnumerable
    {
        class ChildEnumerator : IEnumerator
        {
            ChunkedEnumerable parent;
            int position;
            bool done = false;
            T current;
    
    
            public ChildEnumerator(ChunkedEnumerable parent)
            {
                this.parent = parent;
                position = -1;
                parent.wrapper.AddRef();
            }
    
            public T Current
            {
                get
                {
                    if (position == -1 || done)
                    {
                        throw new InvalidOperationException();
                    }
                    return current;
    
                }
            }
    
            public void Dispose()
            {
                if (!done)
                {
                    done = true;
                    parent.wrapper.RemoveRef();
                }
            }
    
            object System.Collections.IEnumerator.Current
            {
                get { return Current; }
            }
    
            public bool MoveNext()
            {
                position++;
    
                if (position + 1 > parent.chunkSize)
                {
                    done = true;
                }
    
                if (!done)
                {
                    done = !parent.wrapper.Get(position + parent.start, out current);
                }
    
                return !done;
    
            }
    
            public void Reset()
            {
                // per http://msdn.microsoft.com/en-us/library/system.collections.ienumerator.reset.aspx
                throw new NotSupportedException();
            }
        }
    
        EnumeratorWrapper wrapper;
        int chunkSize;
        int start;
    
        public ChunkedEnumerable(EnumeratorWrapper wrapper, int chunkSize, int start)
        {
            this.wrapper = wrapper;
            this.chunkSize = chunkSize;
            this.start = start;
        }
    
        public IEnumerator GetEnumerator()
        {
            return new ChildEnumerator(this);
        }
    
        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    
    }
    private class EnumeratorWrapper
    {
        public EnumeratorWrapper(IEnumerable source)
        {
            SourceEumerable = source;
        }
        IEnumerable SourceEumerable { get; set; }
    
        Enumeration currentEnumeration;
    
        class Enumeration
        {
            public IEnumerator Source { get; set; }
            public int Position { get; set; }
            public bool AtEnd { get; set; }
        }
    
        public bool Get(int pos, out T item)
        {
    
            if (currentEnumeration != null && currentEnumeration.Position > pos)
            {
                currentEnumeration.Source.Dispose();
                currentEnumeration = null;
            }
    
            if (currentEnumeration == null)
            {
                currentEnumeration = new Enumeration { Position = -1, Source = SourceEumerable.GetEnumerator(), AtEnd = false };
            }
    
            item = default(T);
            if (currentEnumeration.AtEnd)
            {
                return false;
            }
    
            while (currentEnumeration.Position < pos)
            {
                currentEnumeration.AtEnd = !currentEnumeration.Source.MoveNext();
                currentEnumeration.Position++;
    
                if (currentEnumeration.AtEnd)
                {
                    return false;
                }
    
            }
    
            item = currentEnumeration.Source.Current;
    
            return true;
        }
    
        int refs = 0;
    
        // needed for dispose semantics 
        public void AddRef()
        {
            refs++;
        }
    
        public void RemoveRef()
        {
            refs--;
            if (refs == 0 && currentEnumeration != null)
            {
                var copy = currentEnumeration;
                currentEnumeration = null;
                copy.Source.Dispose();
            }
        }
    }
    /// Speed Checked.  Works Great!
    public static IEnumerable> Chunk(this IEnumerable source, int chunksize)
    {
        if (chunksize < 1) throw new InvalidOperationException();
    
        var wrapper = new EnumeratorWrapper(source);
    
        int currentPos = 0;
        T ignore;
        try
        {
            wrapper.AddRef();
            while (wrapper.Get(currentPos, out ignore))
            {
                yield return new ChunkedEnumerable(wrapper, chunksize, currentPos);
                currentPos += chunksize;
            }
        }
        finally
        {
            wrapper.RemoveRef();
        }
    }
    #endregion
    

提交回复
热议问题