如何检查变长字符串以查看它们是否以数组中的任何内容开头

时间:2015-07-06 11:08:02

标签: c# php mysql arrays linq

如果问题令人困惑,我道歉,因为我不确定如何说出这个概念。

目前,我正在做的事情是以下几行作为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之前处理,长度为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" );
    }

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

第一个例子是使用嵌套的foreach,我想避免使用嵌套循环。 Linq的例子看起来不错,但我相信这个问题与我要做的事情相反。

以下代码似乎有效,但我不确定它是否尊重数组中项目的顺序。它似乎是,但想要确认,因为我不知道如何观看&#39; 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),而且它们也按照组的长度排序,但它们有一个&#39;成本&#39;我正在计算的字段。

1 个答案:

答案 0 :(得分: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 ");