Skip to content

Instantly share code, notes, and snippets.

@wipiano
Last active October 12, 2017 17:03
Show Gist options
  • Save wipiano/5566578963e247cc58634277b5ea9a01 to your computer and use it in GitHub Desktop.
Save wipiano/5566578963e247cc58634277b5ea9a01 to your computer and use it in GitHub Desktop.
[C#][LINQ] IEnumerable<T> を要素数を指定して分割する 超デリケートな拡張メソッド ref: http://qiita.com/wipiano/items/d217a279e028c95b7899
var result = Enumerable.Range(1, 99).Split(10);
foreach (var splitted in result)
{
System.Console.WriteLine(string.Join(",", splitted));
}
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();
}
}
}
}
var result = Enumerable.Range(1, 99).Split(10).ToList();
var result = Enumerable.Range(1, 99).Split(10).Select(inner => inner.ToList()).ToList();
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