用其他两个列表过滤一个列表

问题描述 投票:0回答:2

考虑以下三个示例列表:

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 文件的完整路径,其名称以 localPatientsIDs 或 RemotePatientsIDs 中的病人 ID 开头。

例如: @"G:\Archive -007_20230526175817297.zip" :文件名 000-007_20230526175817297.zip 以 000-007 开头,这是 RemotePatientsIDs 列表中的一个元素。

患者 ID 不能同时位于 localPatientsIDs 和 archivedFiles 中,因此,这两个列表之间不允许有重复项。但是,archivedFiles 可以包含同样位于 RemotePatientsIDs 中的病人 ID。

我需要获取 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:参数 1:无法从“System.Collections.Generic.IEnumerable”转换为“string”

那么到目前为止我最好的尝试是下面这句话(我承认这对我来说似乎有点混乱)。它总是返回一个空列表。

List<string> archivedFilesToUnzip = archivedFiles.Where(name => archivedFiles.Any(x => x.ToString().Contains(remotePatients.Except(localPatients).ToString()))).ToList();

我发现这些有用的帖子可以帮助我更好地理解Where和Select之间的区别:

此外,我一直在寻找使用 Linq 的任何指示

以及其他链接,但我仍然找不到有效的解决方案。

c# list linq
2个回答
0
投票

您可以尝试这个 LINQ 查询,它会返回预期的结果:

using System.Text.RegularExpressions;

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

// a helper function
var getPatientId = (string input) =>
{
    string pattern = @"\\([^\\_]+)_"; // an appropriate pattern
    Match match = Regex.Match(input, pattern);
    return match.Success ? match.Groups[1].Value : null;
};

var query = from file in archivedFiles
    // elements present in remotePatientsIDs
    where remotePatientsIDs.Contains(getPatientId(file))
          // but not in localPatientsIDs
          && !localPatientsIDs.Contains(getPatientId(file))
    select file;

foreach (var file in query)
    Console.WriteLine(file);

0
投票

C# 是静态(并且大多是强)类型语言(如果您想深入了解,请参阅强类型语言和静态类型语言之间有什么区别?问题和C# 类型系统文章)。这意味着它将检查变量类型并且不会允许很多错误,例如比较字符串和布尔值。

remotePatients.Except(localPatients)
string
的集合,而
name
中的
archivedFiles.Where(name => name
“只是”一个
string
。字符串上的
Contains
可以接受
char
string
中的符号)或另一个
string
,而不是字符串集合,因此会出现编译错误。

您的第二次尝试编译,但不会实现任何有意义的内容 - 如果您将

remotePatients.Except(localPatients).ToString()
分配给变量并检查它或打印到控制台,您将只看到类型名称(准确地说是
System.Linq.Enumerable+<ExceptIterator>d__99
1[System.String]`)显然它不包含在“源”字符串中。

对于你的问题,我建议你这样做:

var missing = remotePatients.Except(localPatients)
    .ToHashSet();
var regex = new Regex(@"\\(?<id>[\d-]+)_\d+\.zip");
List<string> archivedFilesToUnzip = archivedFiles
    .Where(name =>
    {
        var match = regex.Match(name);
        if (match.Success)
        {
            var id = match.Groups["id"].Value;
            return missing.Contains(id);
        }

        return false;
    })
    .ToList();

这使用正则表达式从文件名中提取 id,然后在“丢失”的 id 中搜索它。

© www.soinside.com 2019 - 2024. All rights reserved.