C# 循环遍历两个列表,从列表 #2 中删除重复项

标签 c# arrays list

我有一个目录的文件名数组 (aryFileNames)。我有一个 CSV 文件中的文件名列表 (lstKeepers)。此列表是应该位于目录中的文件的列表。我实际上在做的是在目录中查找孤立文件。

我现在已经重做了这个逻辑 3 次,每次我最终遇到一个需要重做的问题,所以我只想问清楚我应该如何处理这个问题。

我目前的逻辑是这样的:

List<string> lstKeepers = new List<string>(aryKeepers);
DirectoryInfo dir = new DirectoryInfo(txtMSALoc.Text);
FileInfo[] attFiles = dir.GetFiles();
//variable for testing if a keeper was found.
bool bolTest = false;
//Loop through the directory's files
foreach (FileInfo attFile in attFiles)
{
    //Loop through the list of keepers
    foreach (string lstKeeper in lstKeepers){
        if (lstKeeper == attFile.Name)
        {
            //This file is a keeper not an orphan, remove it from the list.
            // This line doesn't actually work.  Is a List the right way to go?
            lstKeepers(lstKeeper).remove;
            bolTest = true;
            break;
        }
    }
    // Code fell out of the loop, see if it found a keeper.
    if (bolTest)
    {
        bolTest=false;
    }
    else
    {
        //CODE TO MOVE FILE INTO ORPHAN DIRECTORY
    }
}

我正在处理多达 200 万个文件的潜在目录(和 keeper 列表),所以这就是我想要不断缩小 keeper 列表及其找到的每个文件的原因,因此它运行的时间越长,事情就会越快。

所以我的第一个问题是,是否有更好的方法来做到这一点?

我的下一个问题是,数组和列表是最好用的东西吗?当你需要删除东西时,我看到了一些关于链表的东西更好。

这是我之前尝试过的简要说明:

1) 同时循环遍历目录列表和守护者列表: 由于大多数情况下两者都是数值 file.name = 123、file.name = 124 等等,我只是比较文件名的值并根据当前对是 < 还是 > 来确定要采取的操作其他或=。但由于缺乏自然排序,这行不通。

2) 只使用两个数组,但从数组中删除项目是不切实际的(因为我必须不断地重新创建数组)。

3)(当前)这似乎是可行的方法,因为我可以删除项目,但后来有人说要使用 LinkedLists 删除项目,因为我厌倦了重新启动这个项目,那是压垮编码员的最后一根稻草: )

感谢任何建议!

更新:这是最终版本,非常感谢大家的帮助!

            string[] aryKeepers;
            if (File.Exists("Keepers.csv"))
            {
                aryKeepers = File.ReadAllLines("Keepers.csv");
            }
            else
            {
                MessageBox.Show("Cannot find 'Keepers.csv' file.", "Missing CSV File Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                aryKeepers = null;
                return;
            }
            List<string> lstKeepers = new List<string>(aryKeepers);
            DirectoryInfo dir = new DirectoryInfo(txtMSALoc.Text);
            FileInfo[] attFiles = dir.GetFiles();
            List<string> lstOrphans = attFiles
                                        .Where(x => !lstKeepers.Contains(x.Name))
                                        .Select(x => x.Name)
                                        .ToList();
            if (lstOrphans.Count > 0){
                intOrphan = lstOrphans.Count;
                lstOrphans.ForEach (lstOrphan => {
                    string strOldFile = txtMSALoc.Text + @"\" + lstOrphan;
                    string strNewFile = dirOrphan + lstOrphan;
                    File.Move(strOldFile, strNewFile);
                });
            }

最佳答案

为什么不只是

List<string> orphans = new List<string>();

// Enumerate files in directory
foreach(string file in attFiles)
{
    // If the filename isn't in the keepers list it must be 
    // an orphan, add it to the orphans list
    if(!lstKeepers.Contains(file.Name))
        orphans.Add(file.Name);
}

后来

foreach(string orphanedFile in orphans)
{ 
    // Move the file
}

我不认为它会有惊人的性能,但你没有提到性能问题 - 只是你无法获得正确的逻辑

我可能还会补充一点,在枚举列表的同时尝试从列表中删除项目(即 foreach 循环)将导致运行时异常,这可能是您遇到的问题之一

编辑:只是为了好玩,因为每个人都喜欢 linq(并且因为 gunr2171 建议)

List<string> orphans = attFiles
                            .Where(x => !lstKeepers.Contains(x.Name))
                            .Select(x => x.Name)
                            .ToList();

那么你可以

orphans.ForEach(orphan => { // Do something });

关于C# 循环遍历两个列表,从列表 #2 中删除重复项,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25143780/

相关文章:

python - 在 Pandas 中定义列类型为 'list'

c# - 在 Silverlight 中为枚举定义扩展方法

c# - 按大写字母拆分字符串

c# - 在 WPF 中,如何从合并字典中引用 App.xaml 中的 StaticResource

javascript - 如何使表格行可单击以显示隐藏的行内容?

C++ 无法翻转 ppm 图像

C# 如何在字符串中写行特定字符串?

c - 如何将指向结构的指针数组作为参数传递给c

python - 将字符串匹配到元组列表

python - 当您尝试在遍历列表元素时删除它会发生什么