【问题标题】:How to check variable length strings to see if they start with anything in the array如何检查可变长度字符串以查看它们是否以数组中的任何内容开头
【发布时间】:2015-07-06 11:08:01
【问题描述】:

如果问题令人困惑,我深表歉意,因为我不确定如何用词来表达这个概念。

目前,我正在做的事情类似于 MySQL 语句,但是我正在将其迁移到 C# 中处理,并计划在直接处理数据后将记录插入数据库,而不是插入到数据库并使用以下概念:

$db->exec('UPDATE `' . date('Y-m',time() - self::DAYS_TO_MERGE) . '` SET `Cost`=0, `Location`=\'Flat Rate World\' WHERE `Cost` IS NULL AND `Caller` IN (' . $FlatRateWO. ') AND SUBSTR(`Dialed`,1,7) IN (\'0114021\',\'0117095\');');
$db->exec('UPDATE `' . date('Y-m',time() - self::DAYS_TO_MERGE) . '` SET `Cost`=0, `Location`=\'Flat Rate World\' WHERE `Cost` IS NULL AND `Caller` IN (' . $FlatRateWO. ') AND SUBSTR(`Dialed`,1,6) IN (\'011420\',\'011420\',\'011852\',\'011353\',\'011353\',\'011972\',\'011972\',\'011379\',\'011379\',\'011351\',\'011351\',\'011886\');');
$db->exec('UPDATE `' . date('Y-m',time() - self::DAYS_TO_MERGE) . '` SET `Cost`=0, `Location`=\'Flat Rate World\' WHERE `Cost` IS NULL AND `Caller` IN (' . $FlatRateWO. ') AND SUBSTR(`Dialed`,1,5) IN (\'01154\',\'01154\',\'01161\',\'01161\',\'01143\',\'01143\',\'01132\',\'01132\',\'01186\',\'01186\',\'01145\',\'01145\',\'01133\',\'01133\',\'01149\',\'01149\',\'01130\',\'01130\',\'01136\',\'01136\',\'01131\',\'01131\',\'01147\',\'01148\',\'01148\',\'01182\',\'01182\',\'01165\',\'01165\',\'01134\',\'01134\',\'01141\',\'01141\',\'01146\',\'01146\',\'01166\',\'01166\',\'01144\');');
$db->exec('UPDATE `' . date('Y-m',time() - self::DAYS_TO_MERGE) . '` SET `Cost`=0, `Location`=\'Flat Rate World\' WHERE `Cost` IS NULL AND `Caller` IN (' . $FlatRateWO. ') AND SUBSTR(`Dialed`,1,4) IN (\'1787\');');

上面的 PHP 代码执行查询,并根据起始数字的长度从最长的数字组开始按顺序排列。这意味着,0114021 的长度为 7 位,在处理 011420 之前得到处理,011420 的长度为 6 位。这是为了防止0111234 设置的价格与011123 不同的情况。

此过程 100% 运行,但速度非常慢(平均大约 0.63 秒/查询超过 100,000 条记录)。实际值来自我必须预处理然后插入数据库的 CSV 文件,所以如果我可以在插入之前对记录进行上述处理和计算,我想这会节省很多时间。

以下是将上述数组转换成C#:

World = new List<string>() { "0114021", "0117095", "011420", "011852", "011353", "011972", "011972", "011379", "011351", "011886", "01154", "01161", "01143", "01132", "01186", "01145", "01133", "01149", "01130", "01136", "01131", "01147", "01148", "01182", "01165", "01134", "01141", "01146", "01166", "01144", "01135", "1787" };

我想知道的是如何有效(尽可能)完成相同的任务,例如比较以下数字以查看它们是否以 World 中的任何内容开头,记住我希望返回最长的匹配首先。

011353123456277 ... should match 011353  
011351334478399 ... should match 01135  
011326717788726 ... should match nothing -- not found.

刚刚尝试了以下代码,没有成功:

    if ( World.All( s => "01197236718876321".Contains( s ) ) ) {
        MessageBox.Show( "found" );
    }

    if ( World.All( s => s.Contains("01197236718876321") ) ) {
        MessageBox.Show( "found" );
    }

使用此处的示例 > Using C# to check if string contains a string in string array

第一个例子是使用嵌套的foreach,我想避免使用嵌套循环。 Linq 示例看起来不错,但我相信问题与我正在尝试做的相反。


以下代码似乎有效,但我不确定它是否尊重数组中项目的顺序。似乎是,但我想确认一下,因为我不知道如何“观察”Linq 的魔法内部发生了什么:

    string foundas = "";
    string number = "01197236718876321";

    if(World.Any( 
        b => {
            if(number.StartsWith(b)) {
                foundas = b;
                return true;
            } else {
                return false;
            }
        }
    ) ) {
        MessageBox.Show( foundas );
    }

一边

我将对这个问题进行跟进,因为下一部分有点复杂,我会抓取一组费率(大约 10,000 个),而且它们也按组的长度排序,但它们有一个我目前正在计算的“成本”字段。

【问题讨论】:

    标签: c# php mysql arrays linq


    【解决方案1】:

    我会使用 StartsWith 检查所有命中,然后简单地获取结果中最长的字符串(通过聚合)。可能有一些比聚合更简单的东西。

    var hit = World.Where( s => source.StartsWith(s)).Aggregate(string.Empty, (max,cur)=> max.Length > cur.Length ? max :cur);
    
    if(!string.IsNullOrEmpty(hit))
        MessageBox.Show( "found "); 
    

    【讨论】:

      猜你喜欢
      • 2021-12-03
      • 1970-01-01
      • 2019-08-24
      • 2015-04-15
      • 2023-01-01
      • 2012-02-05
      • 1970-01-01
      • 1970-01-01
      • 2016-05-02
      相关资源
      最近更新 更多