我有一个List<string>
包含一些路径的列表。
C:\Dir\Test\
C:\MyDir\
C:\YourDir\
C:\Dir\
我想遍历所有元素(使用 LINQ)并从我的列表中删除以其他元素开头的条目。
在我的示例C:\Dir\Test\
中以 - 开头,C:\Dir\
所以我想删除C:\Dir\Test\
.
使用List<T>.RemoveAll()
方法:
sourceList.RemoveAll(x => sourceList.Any(y => x != y && x.StartsWith(y)));
尝试这个:
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)));
怎么样
mylist = mylist.Where(a => mylist.All(b => b == a || !a.StartsWith(b)))
.Distinct()
.ToList();
这将返回一个新列表,其中列表中没有其他项目。
它具有额外的检查以允许返回字符串相同的值,否则将从列表中删除所有项目。
最后,distinct 调用意味着删除了相同字符串的两次出现。
基于 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();
这通过减少每个测试的搜索列表的大小来降低解决方案的复杂性。它仍然需要初始排序。
就我个人而言,我发现这种替代解决方案更难阅读,我的第一个答案更能表达要解决的问题。
最有效的方法是 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
and C:\Directory
)