请考虑以下三个示例列表:
List<string> localPatientsIDs = new List<string> { "1550615", "1688", "1760654", "1940629", "34277", "48083" };
List<string> remotePatientsIDs = new List<string> { "000-007", "002443", "002446", "214", "34277", "48083" };
List<string> archivedFiles = new List<string>{
@"G:\Archive\000-007_20230526175817297.zip",
@"G:\Archive\002443_20230526183639562.zip",
@"G:\Archive\002446_20230526183334407.zip",
@"G:\Archive\14967_20240703150011899.zip",
@"G:\Archive\214_20231213150003676.zip",
@"G:\Archive\34277_20230526200048891.zip",
@"G:\Archive\48083_20240214150011919.zip" };
请注意,中的每个元素archivedFiles
都是 ZIP 文件的完整路径,其名称以 开头,patientID
位于localPatientsIDs
或中remotePatientsIDs
。
例如:@"G:\Archive\000-007_20230526175817297.zip"
:文件名000-007_20230526175817297.zip
以 开头000-007
,它是列表中的一个元素remotePatientsIDs
。
患者 ID 不能同时位于 和localPatientsIDs
,archivedFiles
因此这两个列表之间不允许有重复项。但是archivedFiles
可以包含也位于 中的患者 ID remotePatientsIDs
。
我需要获取文件名以 中存在但不存在于 中archivedFiles
的元素开头的元素。终点是将这些文件解压缩到包含数据库的目录中。remotePatientsIDs
localPatientsIDs
localPatientsIDs
对于给定的示例,我期望得到以下结果:
archivedFilesToUnzip == {
@"G:\Archive\000-007_20230526175817297.zip",
@"G:\Archive\002443_20230526183639562.zip",
@"G:\Archive\002446_20230526183334407.zip",
@"G:\Archive\214_20231213150003676.zip" }
那么,如何使用 LINQ 来做到这一点?
由于我缺乏知识,我期望它会简单到如下程度:
List<string> archivedFilesToUnzip = archivedFiles.Where(name => name.Contains(remotePatients.Except(localPatients)))
我甚至无法编译它,因为Contains
可能无法遍历列表成员,并且我收到消息:
CS1503: Argument 1: cannot convert from 'System.Collections.Generic.IEnumerable<string>' to 'string'
那么,到目前为止,我最好的尝试是以下句子(我承认它对我来说似乎有点混乱)。它总是返回一个空列表。
List<string> archivedFilesToUnzip = archivedFiles.Where(name => archivedFiles.Any(x => x.ToString().Contains(remotePatients.Except(localPatients).ToString()))).ToList();
我发现这些有用的帖子帮助我更好地理解Where
和之间的区别Select
:
- Entity Framework中的 Select 和 Where 之间的区别
- Linq:Select 和 Where 之间有什么区别
另外,我一直在寻找使用 LINQ 的任何方向:
以及其他链接,但我仍然找不到可行的解决方案。
C# 是静态(且大多是强)类型语言(如果您想深入了解,请参阅强类型语言和静态类型语言之间有什么区别?问题和C# 类型系统文章)。这意味着编译器将检查变量类型,并且不会允许很多错误,例如比较字符串和布尔值。
remotePatients.Except(localPatients)
是 的集合,string
而name
在archivedFiles.Where(name => name
“仅仅” 一个string
。Contains
字符串 可以接受char
(a 中的符号string
) 或另一个string
,而不是字符串的集合,因此会出现编译错误。您的第二次尝试可以编译,但不会实现任何有意义的内容 - 如果您分配
remotePatients.Except(localPatients).ToString()
给一个变量并检查它或者将结果打印到控制台,您将只看到类型名称(System.Linq.Enumerable+<ExceptIterator>d__99
确切地说是 1[System.String]`),这显然不是文件名的一部分。对于您的问题,我建议您做以下事情:
这使用正则表达式从文件名中提取 id,然后在“缺失”的 id 中搜索它。
这个特定正则表达式的解释可以在@regex101找到。
下面是一个可以完成您想要的操作的简单 LINQ 查询:
以下是一些细节:
localPatientsIDs.Any(Path.GetFileName(file).StartsWith)
将检查是否有localPatientsIDs
符合条件的项目,即:Path.GetFileName(file).StartsWith
-Path.GetFileName
将从路径中获取文件名,StartsWith
并检查文件名是否以任何元素开头localPatientsIDs
为了更清楚,我将定义这种方法:
然后你可以像这样使用它:
更新
如果您想查看文件名是否以 defined 前缀开头,后跟
_
,请使用以下代码:和修改的方法:
您可以尝试这个 LINQ 查询,它会返回预期的结果: