Как разделить IEnumerable (Of T) на основе шаблона в порядке T? - PullRequest
0 голосов
/ 09 августа 2011

Рассмотрим следующий IEnumerable (Of String):

    Moe1
    Larry1
    Curly1
    Shemp1
    Curly1

    Moe2
    Larry1
    Curly1
    Shemp1
    Curly1
    Curly2
    Shemp2
    Curly1
    Curly2

    Larry2
    Curly1

    Larry3
    Shemp1

Они визуально разделены здесь, чтобы сделать шаблон более удобным для просмотра.Я хочу разделить IEnumerable (Of String) с помощью предиката .StartsWith () на IEnumerable (Of IEnumerable (Of String).

. Правила:

  • каждый разделенподмножество должно иметь Ларри , а может иметь Moe
  • раздел на Moe при Moe встречается
  • , если Ларри следует сразу за Мо , поставьте ему последний Мо
  • , если Ларри немедленно следует за кем-либо еще, раздел на Ларри
  • все остальные марионетки ставятся с текущим разделом
  • все марионетки, кроме Мое и Ларри можно повторить в разделе

Я использую .StartsWith ("Moe") и т. Д., Чтобы определить тип марионетки, но у меня возникают трудностивремя, чтобы выяснить, как разбить этот набор с помощью операторов LINQ, чтобы , если Moe , присутствовал, он представляет заголовок раздела, но с Ларри должен существовать в каждом разделе, он может представлять заголовок раздела, если Мое не предшествует ему.

Как я могу создать IEnumerable (Of IEnumerable (OfСтрока), чтобы результат был разделен так, как я отображаю набор пустыми строками?

Если нет подходящих операторов LINQ для чего-то подобного (я программирую в VB.NET, если есть небольшие различия ввозможности между VB.NET и C #), и мне просто нужно написать метод для этого, я могу это сделать, но я подумал, что это может быть проблема, которая возникает и легко решается с помощью операторов LINQ.

Заранее спасибо.

1 Ответ

2 голосов
/ 09 августа 2011

LINQ здесь, похоже, не является решением, поскольку у вас довольно сложное условие разделения, а структура данных, которую вы хотите получить, не типична для запросов LINQ. AFAIK, единственный оператор LINQ, который предназначен для одновременного знания нескольких элементов последовательности, - это Aggregate, но здесь он не подходит, поскольку мы делаем нечто обратное от агрегирования.

Таким образом, ваша проблема, кажется, решается проще, используя классические циклы, более менее (не проверенные):

public IEnumerable<IEnumerable<string>> Partition(IEnumerable<string> input)
{
    var currPartition = new List<string>();
    string prev = null;

    foreach (var elem in input)
    {
        if (ShouldPartition(prev, elem))
        {
            yield return currPartition;
            currPartition = new List<string>();
        }

        currPartition.Add(elem);
        prev = elem;
    }

    yield return currPartition;
}

private bool ShouldPartition(string prev, string elem)
{
    if (prev == null)
        return false;
    if (elem.StartsWith("Moe"))
        return true;
    if (elem.StartsWith("Larry"))
        return !prev.StartsWith("Moe");
    return false;
}
...