检查字符串值是否为单词

时间:2018-09-12 08:40:14

标签: c# performance linq

我正在开发一种工具来读取包含以下格式的值列表的Excel文件:

public function payments($trans){

    dd($trans);


    Excel::create('export_list_general', function ($file){

    $file->sheet('export', function ($sheet) use ($trans) {

            $sheet->setCellValue('A1', 'Client');
            $sheet->setCellValue('B1', 'name');
            $sheet->setCellValue('C1', 'surname');

            $i = 2;
            foreach ($trans as $tran) {
                $sheet->setCellValue('A' . $i, $tran->name);
                $sheet->setCellValue('B' . $i, $tran->pname);
                $sheet->setCellValue('C' . $i, $tran->psurn);


                $i++;
            }

        });


    })->export('xlsx');

}

该工具使用空格作为分隔符来拆分每个项目的描述,然后检查英语和德语词典(该工具加载时将txt文件加载到字符串列表中)是否是单词。
即:

ID    Description
1     AR2 KSRT FAN W32
2     KSK43 SRTS COOLER S324
3     RT7 MARS 0934X

如果单词上有数字或者它的长度小于3,我不会检查并假设它不是单词。

我正在使用LINQ拆分所有描述的值,然后获得不同的值(每个单词仅搜索一次)。

ID    Words
1     AR2
1     KSRT
1     FAN
1     W32

然后再次使用LINQ来获取所有在描述中带有单词的条目。

List<string> distinctValues = dtCheck.AsEnumerable().SelectMany(r => r.Field<string>(columnName).Split(' ').Select(x => x).Where(s => s.All(char.IsLetter)).Where(y => y.Length > 2).ToList()).Distinct().ToList();

当前此过程大约需要40分钟,我是否可以做些改善性能的事情?

相关信息:
输入文件具有3.411个不同的“单词”。
词典文件中包含〜2.000.000个单词(包括品牌名称等)

对于每个单词,我调用以下函数:

dt = dtCheck.AsEnumerable().Where(x => x.Field<string>(columnName).Split(' ').Any(notNeutralValues.Contains)).CopyToDataTable();

1 个答案:

答案 0 :(得分:1)

由于您的目标是提高性能,因此请执行以下步骤:

  • 创建一个Hashset展平数据,并使用Regex知道所有值是否都是字符。同样,这将消除对单独的Distinct的要求,并且通过将StringComparer.OrdinalIgnoreCase传递给构造函数来区分大小写

     var dataHashSet = new HashSet<string>(dtCheck.AsEnumerable()
                  .SelectMany(r => r.Field<string>("columnName")
                                    .Split(' ')
                                    .Select(x => x)
                                    .Where(s => s.Length > 2 && Regex.IsMatch(s, @"^[a-zA-Z]+$"))),StringComparer.OrdinalIgnoreCase)
    
  • 使用PLinq并行处理dataHashSet

    var result = dataHashSet.AsParallel().Where(x => isNeutralLanguage(x)).ToList();
    
  • 在用于测试的方法isNeutralLanguage中,确保实现如下:

    var dict = new ConcurrentDictionary<string, string>(StringComparer.OrdinalIgnoreCase);
    
    private bool isNeutralLanguage(string entry)
    {
       bool neutral = true;
       var isMatch = dict.TryGetValue(entry,out string entryValue);
       if (isMatch && entryValue != null )
         neutral = false;
       return neutral;
    }
    
  • 不区分大小写,类似于上面的Hashset

  • 它是ConcurrentDictionary,因为通话是multi-threaded

  • 中性检查应为O(1)比较,而不是您正在执行的O(N),您可以根据逻辑要求并快速处理将给定键的值存储为null布尔值,取决于Key是否存在。

  • 根据需要对isNeutralLanguage逻辑进行更改,我做了一些假设

随着算法的改进和处理的并行进行,这些更改将确保您的情况下性能更快得多