Разделить IEnumerable на несколько IEnumerables - PullRequest
0 голосов
/ 28 сентября 2019

Я новичок в linq, мне нужно разделить IEnumerable типа Couple (текст строки, индикатор bool) на несколько IEnumerables на основе индикатора, я пробовал с помощью skipWhile и TakeWhile, но я не нашел решения,входные данные следующие:

Couple("a",false)
Couple("b",false)
Couple("c",true),
Couple("d",false)
Couple("e",false)
Couple("f",true),
Couple("g",true),
Couple("h",true),
Couple("i",false)
Couple("j",true),
Couple("k",true),
Couple("l",false)
Couple("m",false)

Результат должен быть 7 IEnumerables

list1: Couple("a",false)
       Couple("b",false)
list2: Couple("c",true)
list3: Couple("d",false)
       Couple("e",false)
list4: Couple("f",true)
       Couple("g",true)
       Couple("h",true)
list5: Couple("i",false)
list6: Couple("j",true)
       Couple("k",true)
list7: Couple("l",false) 
       Couple("m",false)

Любая помощь, пожалуйста?

Ответы [ 3 ]

2 голосов
/ 28 сентября 2019

Попробуйте это:

public static IEnumerable<IList<Couple>> Split(IEnumerable<Couple> couples)
{
    using (var enumerator = couples.GetEnumerator())
    {
        if (!enumerator.MoveNext())
        {
            yield break;
        }
        var current = enumerator.Current;
        var group = new List<Couple> { current };
        while (enumerator.MoveNext())
        {
            var next = enumerator.Current;
            if (current.Indicator.Equals(next.Indicator))
            {
                group.Add(next);
            }
            else
            {
                yield return group;
                group = new List<Couple> { next };
            }
            current = next;
        }
        yield return group;
    }
}

Пример:

var couples = new List<Couple> 
{
    new Couple("a",false),
    new Couple("b",false),
    new Couple("c",true),
    new Couple("d",false),
    new Couple("e",false),
    new Couple("f",true),
    new Couple("g",true),
    new Couple("h",true),
    new Couple("i",false),
    new Couple("j",true),
    new Couple("k",true),
    new Couple("l",false),
    new Couple("m",false),
};

var groupNr = 1;
foreach (var couplesGroup in Split(couples))
{
    Console.WriteLine($"List {groupNr++}: ");
    foreach (var couple in couplesGroup)
    {
        Console.WriteLine($"{couple.Text, 10}, {couple.Indicator}");
    }
    Console.WriteLine();
}
1 голос
/ 28 сентября 2019

Вот общий метод расширения для разделения последовательностей.Для этого требуется функция, которая проверяет два последовательных элемента и определяет, следует ли разделять эти элементы или нет.Результат true означает разделение элементов.Результат false означает, что нельзя разбивать элементы и хранить их вместе в одной подпоследовательности.

public static class EnumerableExtensions
{
    /// <summary>Splits a sequence to subsequences according to a specified
    /// predicate.</summary>
    /// <param name="splitPredicate">A function to determine if two consecutive
    /// elements should be split.</param>
    public static IEnumerable<IEnumerable<TSource>> SplitByPredicate<TSource>(
        this IEnumerable<TSource> source,
        Func<TSource, TSource, bool> splitPredicate)
    {
        var enumerator = source.GetEnumerator();
        bool finished = false;
        TSource previous = default;
        using (enumerator)
        {
            if (!enumerator.MoveNext()) yield break;
            while (!finished)
            {
                yield return GetSubsequence().ToArray();
            }
        }

        IEnumerable<TSource> GetSubsequence()
        {
            while (true)
            {
                yield return enumerator.Current;
                previous = enumerator.Current;
                if (!enumerator.MoveNext()) { finished = true; break; }
                if (splitPredicate(previous, enumerator.Current)) break;
            }
        }
    }
}

Пример использования:

var subsequences = couples.SplitByPredicate(
    (x, y) => x.Indicator != y.Indicator);
0 голосов
/ 28 сентября 2019

Вот решение без Linq:

class Program
{

  public class Couple
  {
    public string Text;
    public bool Indicator;
    public Couple(string text, bool indicator)
    {
      Text = text;
      Indicator = indicator;
    }
  }

  static void Main(string[] args)
  {
    var list = new List<Couple>();

    list.Add(new Couple("a", false));
    list.Add(new Couple("b", false));
    list.Add(new Couple("c", true));
    list.Add(new Couple("d", false));
    list.Add(new Couple("e", false));
    list.Add(new Couple("f", true));
    list.Add(new Couple("g", true));
    list.Add(new Couple("h", true));
    list.Add(new Couple("i", false));
    list.Add(new Couple("j", true));
    list.Add(new Couple("k", true));
    list.Add(new Couple("l", false));
    list.Add(new Couple("m", false));

    var result = new List<List<Couple>>();

    int index = 0;
    bool last = list[0].Indicator;
    result.Add(new List<Couple>());

    foreach ( var item in list )
    {
      if ( item.Indicator != last )
      {
        index++;
        result.Add(new List<Couple>());
      }
      last = item.Indicator;
      result[index].Add(item);
    }

    for ( index = 0; index < result.Count; index++ )
    {
      Console.WriteLine($"List n°{index}");
      foreach ( var item in result[index] )
        Console.WriteLine($"  text: {item.Text}");
    }

    Console.WriteLine("");
    Console.ReadKey();
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...