Last active
October 12, 2017 17:03
-
-
Save wipiano/5566578963e247cc58634277b5ea9a01 to your computer and use it in GitHub Desktop.
[C#][LINQ] IEnumerable<T> を要素数を指定して分割する 超デリケートな拡張メソッド ref: http://qiita.com/wipiano/items/d217a279e028c95b7899
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var result = Enumerable.Range(1, 99).Split(10); | |
foreach (var splitted in result) | |
{ | |
System.Console.WriteLine(string.Join(",", splitted)); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
namespace Wipiano.Linq | |
{ | |
public static class IEnumerableExtensions | |
{ | |
/// <summary> | |
/// シーケンスを指定した要素数ごとに分割します | |
/// </summary> | |
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int size) | |
{ | |
if (size <= 0) | |
{ | |
throw new ArgumentOutOfRangeException($"{nameof(size)} は 0 より大きくなければなりません"); | |
} | |
if (source == null) | |
{ | |
throw new ArgumentNullException($"{nameof(source)} は null にできません"); | |
} | |
using (var enumerator = new SplitEnumerator<T>(source, size)) | |
{ | |
while (enumerator.HasNext) | |
{ | |
yield return enumerator.Enumerate(); | |
} | |
} | |
} | |
private class SplitEnumerator<T> : IDisposable | |
{ | |
private readonly IEnumerator<T> _enumerator; | |
private readonly int _count; | |
private bool _hasNext; | |
public bool HasNext => _hasNext; | |
public SplitEnumerator(IEnumerable<T> source, int count) | |
{ | |
_enumerator = source.GetEnumerator(); | |
_hasNext = _enumerator.MoveNext(); | |
_count = count; | |
} | |
public IEnumerable<T> Enumerate() | |
{ | |
for (var i = 0; i < _count; i++) | |
{ | |
if (_hasNext) | |
{ | |
yield return _enumerator.Current; | |
} | |
else | |
{ | |
yield break; | |
} | |
_hasNext = _enumerator.MoveNext(); | |
} | |
} | |
public void Dispose() | |
{ | |
_enumerator.Dispose(); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var result = Enumerable.Range(1, 99).Split(10).ToList(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var result = Enumerable.Range(1, 99).Split(10).Select(inner => inner.ToList()).ToList(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static IEnumerable<IEnumerable<T>> Split<T>(this IEnumerable<T> source, int size) | |
{ | |
if (size <= 0) | |
{ | |
throw new ArgumentOutOfRangeException($"{nameof(size)} は 0 より大きくなければなりません"); | |
} | |
if (source == null) | |
{ | |
throw new ArgumentNullException($"{nameof(source)} は null にできません"); | |
} | |
var list = new List<T>(size); | |
foreach (var item in source) | |
{ | |
list.Add(item); | |
if (list.Count == size) | |
{ | |
yield return list.ToArray(); | |
list.Clear(); | |
} | |
} | |
if (list.Any()) | |
{ | |
yield return list; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment