将数组的值与字符串 PHP 匹配
Posted
技术标签:
【中文标题】将数组的值与字符串 PHP 匹配【英文标题】:Matching values of an array against a string PHP 【发布时间】:2011-07-22 04:51:49 【问题描述】:我正在做一个小项目,我需要一些帮助。我有一个包含 150,000 行的 CSV 文件(每行有 10 列数据)。我正在使用 fscvread 读取文件,并且在循环期间,我想将每行的其中一列(称为 stringx)与 10,000 个单词的数组进行匹配。如果 stringx 中存在 10,000 个单词中的任何一个,则使用 preg_replace 将其删除。
现在这一切都很好。我一切正常,但问题是,它太慢了。
我尝试了 2 种方法来匹配数组。 1)我使用explode(“”,$stringx)将stringx转换为数组,然后使用array_diff($array_stringx,$array_10000); 2) 在 $array_10000 上使用 foreach 并在 $stringx 上使用 preg_replace
方法 1 大约需要 60 秒来遍历 200 行数据,方法 2 可以在 60 秒内循环 500 行。
有没有更好的方法来做到这一点?
再次,我正在寻找一种有效的方法来(基本上)array_diff 10,000 个单词的数组与 150,000 个字符串一次一个。
非常感谢您的帮助。
【问题讨论】:
听起来像数据库最适合这个。 您的字典需要数组以外的东西。可以加快字典查找时间的方法。内存消耗最多是微不足道的。 彼得你能详细说明一下吗? 您是否至少对代码进行了一次分析,以确保瓶颈是代码的那部分? 二进制搜索、纯字符串等。优化查找速度而不是内存消耗。您可能需要对字典进行排序,甚至可能对其进行分组。 【参考方案1】:以下只是一种选择。它可能会也可能不会满足您的要求。
它在我的笔记本电脑上使用 10k 单词字典和 15k 字符串执行 84 次操作/秒。
缺点是它不会删除单词周围的空格。
$wordlist 就是每行一个单词,可以是一个文件。
$dict = array_flip(preg_split('/\n/',$wordlist));
function filter($str,$dict)
$words = preg_split('/\s/',$str);
sort($words);
$words = array_unique($words);
foreach ($words as $word)
if (key_exists($word,$dict))
$removeWords[] = '/\b' . $word . '\b/';
return preg_replace($removeWords, '', $str);
另一个执行速度更快的示例(107ops/s,15kb 字符串和 10k 单词字典)
function filter2($str,$dict)
$words = preg_split('/\b/',$str);
foreach ($words as $k => $word)
if (key_exists($word,$dict))
unset($words[$k]);
return implode('', $words);
【讨论】:
这看起来非常棒。问题:字典中的某些行实际上是 2 个单词,例如。圣诞老人。由于该函数将 $str 分解为一个数组,因此 Santa 和 Cruz 成为键,然后在匹配中返回为 false。 啊,是的……当然。还没有时间解决这个问题。但这会改变一些事情【参考方案2】:不爆炸 stringx 怎么样,为 $array_10000 中的每个单词做一个stripos()?
像这样:
foreach ($array_10000 as $word)
if (stripos($stringx, $word) !== false)
// do your stuff
【讨论】:
foreach ($array_10000 as $city) $stringx= preg_replace("/\b($city)\b/i", '', $stringx);这正是我正在做的事情,它每分钟大约有 500 个关键字,这太慢了。 您正在使用 preg_replace,并且众所周知,匹配正则表达式通常很慢。使用 stripos 检查出现,然后在发现出现时应用正则表达式可能会更快一些,尽管我还没有测试过。【参考方案3】:您的 10000 字数组是否已排序?如果没有,请先尝试排序。
编辑:好的,因为它已排序,我猜也许 php 的 array_search 不进行二进制搜索,所以我会寻找二进制搜索实现并使用它。如果它确实只是一个线性搜索,那么您将通过这种方式获得一个数量级的速度提升。
【讨论】:
是的,它是按字母顺序排序的。【参考方案4】:PHP 不是速度语言,但我想你知道这一点。我必须在我正在编写的项目中做类似的事情,我正在用 PHP 编写一个文件,然后使用独立的 Matlab 读取该文件,处理它并将其输出另一个。
您也可以这样做并用 C 语言编写一个与array_diff()
相同的小程序。我认为会有很大的不同,虽然我没有做过任何测试。
【讨论】:
【参考方案5】:我没有测试过这个,但我突然想到了:
您可以尝试使用正则表达式预先解析文件以获得要过滤的 150,000 个单词(基于列分隔符),然后您可以进行文本替换,根据 this article I googled 选择最佳函数。
希望对你有帮助!干杯!
【讨论】:
【参考方案6】:您可以只做foreach
和implode
。
$words = array("one","two", "three");
$number = 0;
foreach ($words as $false_array)
$number += 1;
$array[$number] = $false_array;
echo "Added ". $false_array . ". ";
foreach ($words as $false_array)
echo "Array Contains " . $false_array . ". ";
如果你在 php 中执行这个,你会得到:
Added one. Added two. Added three. Array Contains one. Array Contains two. Array Contains three.
【讨论】:
以上是关于将数组的值与字符串 PHP 匹配的主要内容,如果未能解决你的问题,请参考以下文章
javascript - 在对象数组中,返回任何值与特定字符串匹配的对象
如果字符串数组中的列名在字符串数组中具有匹配的值,则获取DataRow