Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 迭代和比较两个类列表的更快方法_C# - Fatal编程技术网

C# 迭代和比较两个类列表的更快方法

C# 迭代和比较两个类列表的更快方法,c#,C#,我需要遍历并比较2个类列表,比较2个并输出匹配的记录。这需要几个小时,我想不出一个方法来加快这个过程。名单上大约有60万条记录。下面是我的类代码和用于迭代和比较的代码 class Person { string NPI; string address; string zip5; string lname; string lsk; string state; string fname; string zipfull; stri

我需要遍历并比较2个类列表,比较2个并输出匹配的记录。这需要几个小时,我想不出一个方法来加快这个过程。名单上大约有60万条记录。下面是我的类代码和用于迭代和比较的代码

class Person
{
    string NPI;
    string address;
    string zip5;
    string lname;
    string lsk;
    string state;
    string fname;
    string zipfull;
    string seqNo;

    public Person(string npi, string Address, string Zip5, string Lname, string LSK, string st, string Fname, string zipFull, string seqno)
    {
        this.NPI = npi;
        this.address = Address;
        this.zip5 = Zip5;
        this.lname = Lname;
        this.lsk = LSK;
        this.state = st;
        this.fname = Fname;
        this.zipfull = zipFull;
        this.seqNo = seqno;
    }

    public string getNPI()
    {
        return NPI;
    }

    public string getzip5()
    {
        return zip5;
    }

    public string getaddress()
    {
        return address;
    }
    public string Full()
    {
        string full = NPI + "," + address + "," + zip5 + "," + lname + "," + lsk + "," + state + "," + fname + "," + zipfull + "," + seqNo;
        return full;
    }
}
下面是用于遍历的代码。fuzz.ratio是我下载的一个模糊匹配nuget包,我知道这不是问题,因为我用它做了速度测试,速度非常快

string inputfile = @"C:\Input_File_150k.csv";
string blacklist = @"C:\Blacklist1.csv";
List<Person> input = Readcsv(inputfile);
List<Person> BL = Readcsv(blacklist);

string outputtest = @"C:\outputtest.csv";
StringBuilder csvcontent = new StringBuilder();

int lengthinput = input.Count();
for(int i = 0; i <lengthinput; i++)
{
    int lengthbl = BL.Count();
    for(int x = 0; x < lengthbl; x++)
    {
        if(input[i].getzip5() == BL[x].getzip5())
        {
            if(input[i].getNPI() == BL[x].getNPI())
            {
                if(Fuzz.Ratio(input[i].getaddress(),BL[x].getaddress()) > 90)
                {
                    csvcontent.AppendLine(input[i].Full());
                }
            }
        }
    }
}

File.AppendAllText(outputtest, csvcontent.ToString());

您可以遍历每个列表一次,将所有值放入哈希映射中。例如,您可以使用邮政编码作为键,值是匹配该邮政编码的人员的数组

然后,您可以一次遍历一条记录,只需将每个hashmap bucket中的人相互比较


除非你所有的人都在同一个邮政编码中,如果是这样的话,希望你的其中一个键能起作用,这应该比N^2比较快。根据每个桶中有多少人,应该更接近于。我认为这部分代码可能比较慢

字符串完整=NPI+,+地址+,+zip5+,+lname+,+lsk+,+state+,+fname+,+zipfull+,+seqNo


如果您在这些属性上执行csvcontent.Append,并手动而不是使用Full,该怎么办?ps:它需要增加一种从外部阅读的可能性,因此除了上面的注释和使用字典之外,还可以使用public get/private set

, 在你的循环中

int lengthinput = input.Count();
    **int lengthbl = BL.Count();** //move out of the loops

    for(int i = 0; i <lengthinput; i++)
    {
        **var inputi = input[i];**  //move out of the inner loop
        for(int x = 0; x < lengthbl; x++)
        {
            **var blx =  BL[x];**
            if(inputi.getzip5() == blx.getzip5())
            {
                if(inputi.getNPI() == blx.getNPI())
                {
                    if(Fuzz.Ratio(inputi.getaddress(),blx.getaddress()) > 90)
                    {
                        csvcontent.AppendLine(inputi.Full());
                    }
                }
            }
        }
    }

我肯定会实现IEqualityComparer接口

这使得代码更加简洁,并且还可以从集合上可用的一些Linq扩展方法中获益

这些也支持类似并行性的东西


尝试从一个列表中创建一个字典以用作查找,同时迭代另一个列表。这将使复杂度从多项式变为线性

string inputfile = @"C:\Input_File_150k.csv";
string blacklist = @"C:\Blacklist1.csv";
List<Person> input = Readcsv(inputfile);
var blAddresses = Readcsv(blacklist).ToDictionary(
    x => (Zip : x.getzip5(), NPI : x.getNPI()),
    x => x.getaddress());

string outputtest = @"C:\outputtest.csv";
StringBuilder csvcontent = new StringBuilder();

int lengthinput = input.Count();
for(int i = 0; i <lengthinput; i++)
{
    var zip = input[i].getzip5();
    var npi = input[i].getNPI();

    if(blAddresses.TryGetValue((zip,npi), out var blAddress)
    {
        if(Fuzz.Ratio(input[i].getaddress(),blAddress) > 90)
        {
            csvcontent.AppendLine(input[i].Full());            
        }
    }
}

File.AppendAllText(outputtest, csvcontent.ToString());

我能想到的唯一方法就是将搜索并行化。您还可以降低您的时间复杂度,因为您现在的算法具有^2时间复杂度。您可以将其中一个转换为以zip和NPI为键的字典,然后将其用作查找,同时循环另一个。这会将复杂性从On*m更改为On+m,其中n和m是每个列表的长度。此外,您确实应该从使用get方法更改为只读属性公共字符串NPI{get;}如果您的代码有效,并且您希望查看代码的所有方面,并且您的问题符合他们的标准,你可以在上问这个问题。实际上他们需要对zip和NPI进行哈希运算。任何东西都比在N^2没有哈希映射要快,但是是的,通过多个值对存储桶进行哈希映射会更好。在列表上运行Count扩展方法时,如果您这么想的话,它只会获取Count属性值,而不会实际迭代集合以获取计数。所以我刚刚尝试了这个方法。问题是某些NPI为空,因此它告诉我,当zip和空白npi是相同的。有没有办法让我把它忽略掉NPIs@bigs89你想完全忽略这些,还是仍然需要匹配空白NPI,具体地说,输入文件是否有一个空白NPI,您想与黑名单中的空白NPI相匹配?@ BigS89i,我用一种替代方法更新了我的答案,它将使您当前的代码给出重复的ZIP/NPI值,或者您可以过滤掉空白的NPIs。但这真的取决于你希望得到的确切数据以及你想如何处理它。非常感谢你,这起到了作用,将大大加快我的过程。还有一个问题,如果我使用这个,并且想要模糊匹配地址以外的多个字段,我会只做x=>x.getaddress,p=>p吗。getlnam@bigs89您可以只执行x=>x来获取整个对象,也可以执行x=>Address:x.getaddress、Inam:x.getInam和命名。
string inputfile = @"C:\Input_File_150k.csv";
string blacklist = @"C:\Blacklist1.csv";
List<Person> input = Readcsv(inputfile);
var blAddresses = Readcsv(blacklist)
    .GroupBy(x => (Zip : x.getzip5(), NPI : x.getNPI()))
    .ToDictionary(
        grp => grp.Key, 
        grp => grp.Select(y => y.getAddress()).ToList());

string outputtest = @"C:\outputtest.csv";
StringBuilder csvcontent = new StringBuilder();

int lengthinput = input.Count();
for(int i = 0; i <lengthinput; i++)
{
    var zip = input[i].getzip5();
    var npi = input[i].getNPI();

    if(blAddresses.TryGetValue((zip,npi), out var blAddressList)
    {
        foreach(var blAddress in blAddressList)
        {
            if(Fuzz.Ratio(input[i].getaddress(),blAddress) > 90)
            {
                csvcontent.AppendLine(input[i].Full());       
            }     
        }
    }
}

File.AppendAllText(outputtest, csvcontent.ToString());
var blAddresses = Readcsv(blacklist)
    .Whree(x => x.getNPI().Length > 0) 
    .ToDictionary(
        x => (Zip : x.getzip5(), NPI : x.getNPI()),
        x => x.getaddress());