使用 linq 获取路径的所有父级

发布于 2024-10-21 17:46:19 字数 1122 浏览 2 评论 0原文

我想在没有显式循环的情况下获取路径的所有父级,以便我可以完全消除此方法。

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

更新:

@Tomas Petricek的回答让我Jon Skeet 的生成器实现 我最终得到以下结果:

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);
        }
    }
}

I'd like to get all parents of a path without an explicit loop so that I can eliminate this method entirely.

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

How could this be done cleanly with LINQ?

given

c:\a\b\c

should return the following (order doesn't matter)

c:\a
c:\a\b

update:

@Tomas Petricek's answer led me to Jon Skeet's Generator implementation and I ended up with the following:

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

using

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);
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

东北女汉子 2024-10-28 17:46:19

Enumerable 提供的标准方法不够强大,无法轻松编码 while 循环。如果您想通过调用某些通用方法来重写代码,您还需要实现一些通用方法。如果添加 Generate 方法,您的问题可以得到很好的解决:

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

Generate 方法的想法是,它不断重复调用提供的 lambda 函数来生成新状态(在此case 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;
  }
}

该方法本质上只是隐藏了原始方法中使用的可重用模式。特定行为作为函数传递,因此您可以将该方法用于许多不同的目的。

The standard methods provided by Enumerable aren't powerful enough to encode while loop easily. If you want to rewrite the code by calling some general purpose method, you'll need to implement some general purpose method too. Your problem could be nicely solved if you added a Generate method:

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

The idea of the Generate method is that it keeps calling the provided lambda function repeatedly to generate new state (in this case path) until it returns null. The method yields all generated values as it goes. You can write Generate like this:

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;
  }
}

The method essentially just hides a reusable pattern that was used in your original method. The specific behavior is passed as a function, so you could use the method for many different purposes.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文