如何比较两个数组的内容并返回重复文件的索引?

时间:2018-08-18 21:19:05

标签: c# .net

我已经建立了一种比较两个文件目录中文件的方法,如果存在以布尔形式重复的文件,它将返回。但是,实际上希望它返回文件名或文件在其数组中的索引,这样我就可以删除该文件,因此将文件移到一个目录时它们不会造成任何麻烦。我试图将“ ==” compare语句转换为一个字符串,希望它能给出文件名,但是我忘了,因为它是布尔运算,只会返回true或false。

static public string ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
    {
        string NoDuplicateMods = "There are no duplicate mods";
        foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
        {
            foreach (var  ModInModsDirectory in SimsModsDirectory)
            {
                if (ModInDownloadDirectory == ModInModsDirectory)
                {

                    string DuplicateMod = (ModInDownloadDirectory == ModInModsDirectory).ToString();
                    return DuplicateMod;
                }
                else
                {
                    return NoDuplicateMods;
                }
            }
        }
        return NoDuplicateMods;
    }

4 个答案:

答案 0 :(得分:3)

您可以通过以下方式获取匹配字符串的索引

var result = SimsModDownloadDirectory.Select((x, i) => 
                 {return (SimsModsDirectory.Contains(x) ? i :-1);})
                 .Where(x => x != -1);
foreach(int index in result)
   Console.WriteLine(index);

想法如下:
用第一个列表中的所有字符串(x)进行枚举,并带有重载,如果第二个列表中包含了枚举字符串,则重载也为我们提供了枚举字符串(i)的索引,否则返回-1。最后,使用Select仅提取非-1值的地方

当然,仅返回重复项的名称要简单得多

var result = SimsModDownloadDirectory.Intersect(SimsModsDirectory);
foreach(string name in result)
   Console.WriteLine(name);

这些方法基于要比较的两个字符串之间的精确匹配。因此,字符串“ Steve”将与字符串“ steve”不匹配。
如果您的要求是忽略比较中的大小写,则可以更改为

var result = SimsModDownloadDirectory.Select((x, i) => 
             {
                return (SimsModsDirectory.Contains(x,  
                        StringComparer.CurrentCultureIgnoreCase) ? i :-1);
             }).Where(x => x != -1);

或到

var result = SimsModDownloadDirectory.Intersect(SimsModsDirectory,  
                           StringComparer.CurrentCultureIgnoreCase);

答案 1 :(得分:1)

代码中的else就是问题。

示例代码(未经测试)

    static public string ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
    string NoDuplicateMods = "There are no duplicate mods";
    foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
    {
        foreach (var  ModInModsDirectory in SimsModsDirectory)
        {
            if (ModInDownloadDirectory == ModInModsDirectory)
            {
                return ModInModsDirectory;
            }
        }
    }
    return NoDuplicateMods;
}

以上内容仅返回第一个重复项。对于所有重复项,您必须维护一个列表并在最后将其返回

static public List<string> ModFileDupilcate(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
    var duplicateDirs = new List<string>();

    foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
    {
        foreach (var  ModInModsDirectory in SimsModsDirectory)
        {
            if (ModInDownloadDirectory == ModInModsDirectory)
            {
                duplicateDirs.Add(ModInModsDirectory);
            }
        }
    }
    return duplicateDirs;
}

答案 2 :(得分:1)

我不确定您要达到什么目标。您的代码没有告诉我们返回值应该是什么。如果要告诉呼叫者“文件名不存在/不重复”,则可以轻松返回bool。如果要返回“重复文件名”,则应返回string[]FileInfo[]IReadOnlyCollection<string>或类似的名称。返回集合或数组的好处是,调用者可以通过检查返回值的Length / Count来轻松查看是否存在重复项。

使用嵌套的for循环会导致O(n * m)的性能下降。使用HashSet或LINQ的Intersect方法,您可以轻松实现O(n + m)的目标:

public static IReadOnlyList<string> FindDuplicateModFiles(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
    var set = new HashSet<string>(SimsModDownloadDirectory);
    var result = new List<string>();
    foreach (string file in SimsModsDirectory)
    {
        if (set.Contains(file))
            result.Add(file);
    }
    return result.AsReadOnly();
}

或使用LINQ:

public static IEnumerable<string> FindDuplicateModFiles2(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
    return SimsModDownloadDirectory.Intersect(SimsModsDirectory);
}

如果要从第一个集合中删除重复项,最好的选择是LINQ的Except方法:

public static IEnumerable<string> GetNonDuplicatesInFirst(string[] SimsModDownloadDirectory, string[] SimsModsDirectory)
{
    return SimsModDownloadDirectory.Except(SimsModsDirectory);
}

答案 3 :(得分:0)

    static public IEnumerable<string> ModFileDupilcate(string[] SimsModDownloadDirectory, 
       string[] SimsModsDirectory)
    {
        var result = SimsModDownloadDirectory.Select((x, i) => 
            SimsModsDirectory.Contains(x) ? x : string.Empty).
            Where(x => !string.IsNullOrEmpty(x));
        return result;
    }

调用方法如:

    var resultOfDublicateFiles = ModFileDupilcate(SimsModDownloadDirectory,SimsModsDirectory);

public static bool ModFileDupilcate(string[] SimsModDownloadDirectory, 
       List<string> SimsModsDirectory,out List<string> dublicatedFiles)
    {
        dublicatedFiles = new List<string>();
        foreach (var ModInDownloadDirectory in SimsModDownloadDirectory)
        {
            foreach (var  ModInModsDirectory in SimsModsDirectory)
            {
                if (ModInDownloadDirectory == ModInModsDirectory)
                {   
                    dublicatedFiles.Add(ModInModsDirectory);
                }
            }
        }
        return dublicatedFiles.Count > 0;
    }

调用方法如:

List<string> dublicatedFiles;
bool hasDublicatedFiles= ModFileDupilcate(new string["a","b","c"],new string["b","c","d","f"],out dublicatedFiles);