получить всех родителей пути с linq - PullRequest
2 голосов
/ 13 марта 2011

Я хотел бы получить все родительские элементы пути без явного цикла, чтобы я мог полностью исключить этот метод.

private static IEnumerable<string> GetParentPaths(string path)
{
    while (Path.GetDirectoryName(path) != Path.GetPathRoot(path))
    {
        path = Path.GetDirectoryName(path);
        yield return path;
    }
}

Как это можно сделать чисто с помощью LINQ?

учитывая

c:\a\b\c

должен вернуть следующее (порядок не имеет значения)

c:\a
c:\a\b

обновление:

@ Ответ Томаса ПетричекаЯ Реализация генератора Джона Скита , и я получил следующее:

path.Generate(Path.GetDirectoryName)
    .Skip(1) // the original
    .TakeWhile(p => p != Path.GetPathRoot(p))

с использованием

public static class TExtensions
{
    public static IEnumerable<T> Generate<T>(this T initial, Func<T, T> next) 
    {
        var current = initial;
        while (true)
        {
            yield return current;
            current = next(current);
        }
    }
}

1 Ответ

4 голосов
/ 13 марта 2011

Стандартные методы, предоставляемые Enumerable, недостаточно мощны, чтобы легко кодировать цикл while. Если вы хотите переписать код, вызвав какой-то метод общего назначения, вам также потребуется реализовать метод общего назначения. Ваша проблема может быть хорошо решена, если вы добавите метод Generate:

EnumerableEx.Generate(path, path => 
  Path.GetDirectoryName(path) != Path.GetPathRoot(path) 
  ? Path.GetDirectoryName(path) : null);

Идея метода Generate состоит в том, что он продолжает неоднократно вызывать предоставленную лямбда-функцию для генерации нового состояния (в данном случае path), пока не вернет null. Метод возвращает все сгенерированные значения по ходу. Вы можете написать Generate так:

static IEnumerable<T> Generate<T>(T initial, Func<T, T> next) {
  T current = initial;
  while(true) {
    current = next(current);
    if (current == default(T)) return;
    yield return current;
  }
}

Метод по существу просто скрывает шаблон многократного использования, который использовался в вашем исходном методе. Определенное поведение передается как функция, поэтому вы можете использовать этот метод для разных целей.

...