我有一个包含一些路径的列表List<string>
。
C:\Dir\Test\
C:\MyDir\
C:\YourDir\
C:\Dir\
我想浏览所有元素(使用LINQ)并删除从列表中的其他元素开始的条目。
在我的示例C:\Dir\Test\
中以C:\Dir\
开头 - 所以我想删除C:\Dir\Test\
。
答案 0 :(得分:9)
使用List<T>.RemoveAll()
方法:
sourceList.RemoveAll(x => sourceList.Any(y => x != y && x.StartsWith(y)));
答案 1 :(得分:3)
试试这个:
myInitialList.RemoveAll(x =>myInitialList.Any(q => q != x && q.StartsWith(x)));
或者,如果您想保留原始列表,这是获取与您的条件不符的所有记录的方法:
List<string> resultList = myInitialList.Except(x => myInitialList.Any(q => q != x && q.StartsWith(x)));
答案 2 :(得分:1)
怎么样
mylist = mylist.Where(a => mylist.All(b => b == a || !a.StartsWith(b)))
.Distinct()
.ToList();
这将返回一个新列表,其中列表中没有其他项目以它开头。
它有额外的检查,允许返回字符串相同的值,否则所有项目都将从列表中删除。
最后,不同的调用意味着删除了两次相同的字符串。
在nsinreal的评论和解决方案的基础上,您可以执行类似
的操作myList = myList.OrderBy(d => d)
.Aggregate(new List<string>(),
(list, item) => {
if (!list.Any(x => item.StartsWith(x)))
list.Add(item);
return list;
}).ToList();
这通过减少每个测试的搜索列表的大小来降低解决方案的复杂性。它仍然需要初步排序。
我个人觉得这个替代解决方案难以阅读,我的第一个答案更能表达要解决的问题。
答案 3 :(得分:1)
最有效的方法是IMO对路径进行排序,然后迭代它们并仅返回那些不是以前一个开始的路径,即:
public static IEnumerable<string>
GetRootPathsOfSet(this IEnumerable<string> paths)
{
var sortedSet = new SortedSet<string>(paths,
StringComparer.CurrentCultureIgnoreCase);
string currRoot = null;
foreach (var p in sortedSet)
{
if (currRoot == null ||
!p.StartsWith(currRoot, StringComparison.InvariantCultureIgnoreCase))
{
currRoot = p;
yield return currRoot;
}
}
}
一些注意事项:
StartsWith
方法不安全(例如C:\Dir
和C:\Directory
)