【问题标题】:How to find duplicates in a list of strings of server path names如何在服务器路径名字符串列表中查找重复项
【发布时间】:2020-07-21 21:59:40
【问题描述】:

我正在尝试在服务器的路径名字符串列表中查找重复项: 我的路径看起来像\\UTIR\STORAGE\10-23-2015\DEPOSITS\123_DEPOSIT_10-23-2015_1.pdf 我将不得不检查其中的 50 个,我需要检查路径的结尾 \123_DEPOSIT_10-23-2015_1.pdf 以确保没有重复。

List<string> manypaths = (List<string>)TempData["temp"];
        var list= new List<string>();
        foreach (var item in manypaths)
        {
            if(list.Contains(item))
            {
                
            }
            else
            {
                list.Add(item);
            }
        }

我正在使用 dotnetzip 库,并且尝试过 ContainsEntry、Contains。以及我在网上找到的所有其他内容。当我将这些文件添加到 zip 文件中时,我收到一个错误:

System.ArgumentException: '已添加具有相同键的项。

using (Ionic.Zip.ZipFile zip = new Ionic.Zip.ZipFile())
        {
            
            zip.AddFiles(list, @"\");

             
            MemoryStream output = new MemoryStream();

            zip.Save(output);
            return File(output.ToArray(), "application/zip");

        }

【问题讨论】:

  • 为什么要检查路径的最后一个?整个路径不重复?
  • @Sajid 当有重复时它会抛出一个错误。根据文件的不同,路径的最后部分前面可能有不同的名称。但是如果最后一部分是相同的,它将通过那个重复的错误。所以我的想法是抓住路径的最后一部分,然后在将其添加到我的 zip 文件时检查是否有重复项。
  • 对于此数据,HashSet 可能比 List 更好。

标签: c# asp.net-mvc linq dotnetzip


【解决方案1】:

要通过最后一部分获得不同的路径,您可以使用group by 最后一部分并获取第一个元素,如以下代码:

List<string> distinctFiles = files
    .GroupBy(x => x.Split(new char[] { '\\' }).Last())
    .Select(x => x.First())
    .ToList();

或者

List<string> distinctFiles = files
    .GroupBy(x => Path.GetFileName(x))
    .Select(x => x.First())
    .ToList();

测试用

List<string> files = new List<string>
{
    @"\\UTIR\STORAGE\10-23-2015\DEPOSITS\123_DEPOSIT_10-23-2015_1.pdf",
    @"\\UTIR\STORAGE1\10-23-2015\DEPOSITS\123_DEPOSIT_10-23-2015_1.pdf",
    @"\\UTIR\STORAGE\10-23-2015\DEPOSITS\123_DEPOSIT_10-23-2015_11.pdf",
};

注意,第一个和第二个是重复的,在不同的路径中

结果

"\\UTIR\STORAGE\10-23-2015\DEPOSITS\123_DEPOSIT_10-23-2015_1.pdf"
"\\UTIR\STORAGE\10-23-2015\DEPOSITS\123_DEPOSIT_10-23-2015_11.pdf"

希望对您有所帮助。

【讨论】:

  • 谢谢!!!!这正是我所需要的。 LINQ 很棒,我必须做得更好。非常感谢您的宝贵时间!
  • 如果两个条目仅区分大小写(a.pdfb.pdf)怎么办?
  • 请记住,使用此答案,您会丢失 zip 中的文件。如果该文件包含不同的数据,则可能是必需的,并且您需要消除名称的歧义。请参阅我的答案以获得澄清
【解决方案2】:

您可以使用 LINQ 轻松做到这一点。

manyPaths
  //.Select(x => x.Split(new char[] { '\\' }).Last()) // drop this
  .Select(x => x.ToLower())
  .Distinct()
  .ToList()

这将确保列表没有重复项。如果您仍然收到错误,则可能是其他问题。

编辑

如果您需要删除重复的文件名,但保留完整路径。您要么会丢失文件,要么必须重命名它们(例如 file.txt、1file.txt、2file.txt 等)

var fileGroups = manyPaths
        .Select(x => new { Path = x, Name = x.Split(new char[] { '\\' }).Last().ToLower() })
        .GroupBy(x => x.Name)
        .ToList();


//TODO: init your zip

foreach(var group in fileGroups)
{
    int count = 0;

    foreach(var file in group)
    {
        var newName = count > 0 ? count + group.Key : group.Key;
        //TODO: save your file to zip
        count++;
    }
}

【讨论】:

  • 这正是我所需要的!现在我收到一条错误消息,说当我的程序点击 zip.Save(output) 时文件路径不存在。
  • 删除第一个选择(拆分).... 只需选择完整路径。除非您在不同的文件夹中有相似的文件名并且 Ionic 关心这一点,否则应该可以工作
  • 所以我想我需要摆脱重复并留下完整的路径。无论如何用 LINQ 做到这一点?
  • 我刚刚尝试过,现在它没有摆脱重复。
  • 有没有一种方法可以让我在文件末尾添加一个时间戳,并且无论如何都会使它独一无二?
猜你喜欢
  • 2019-11-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-07
  • 2019-04-30
相关资源
最近更新 更多