首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >查找重复/冲突时的数组循环性能

查找重复/冲突时的数组循环性能
EN

Stack Overflow用户
提问于 2014-04-08 15:33:25
回答 3查看 76关注 0票数 1

这段代码通过一个事件数组循环,每个事件都有一个开始和结束时间.并简单地设置一个“匹配”键来表示它已经匹配了另一个事件(即冲突来解决):

代码语言:javascript
复制
<?php

$results = array(
        array('from' => 1, 'to' => 3),
        array('from' => 3, 'to' => 6),
        array('from' => 7, 'to' => 9),
        array('from' => 4, 'to' => 8),
    );

$k = 0;

foreach ($results as $p_id => $p_result) {

    foreach ($results as $c_id => $c_result) {
        if ($p_id == $c_id) {
            continue;
        }
        $k++;
        if ($p_result['from'] < $c_result['to'] && $p_result['to'] > $c_result['from']) {
            $results[$p_id]['match'] = $c_id;
            break;
        }
    }

}

print_r($results);
echo $k;

?>

这本身并不一定是缓慢的,但可能是当成千上万的事件被检查时.例如,对事件使用DateTime对象或UNIX时间戳。

在我的电脑上尝试3000个随机事件需要大约1秒的“中断”时间和3秒的时间。

往返碰撞检查本身是由:Comparing date ranges激发的。

我看到的主要问题是,一旦事件1被检查为事件2-4,那么事件2-4实际上不需要对照1来检查自己:

代码语言:javascript
复制
$results[$p_id]['match'] = $c_id;
$results[$c_id]['match'] = $p_id;

但是,我想不出一种优雅的工作方式,尽管这样做并不会使代码更难阅读。

一种可能的方法是为那些“通过”检查的事件创建一个新的数组,但我怀疑在数组中添加/删除元素的内存管理远远超过执行简单的整数检查。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2014-04-08 15:43:12

与使用foreach不同,您可以在那里使用两个数字循环。然后,您的“内循环”可以从当前的outer value+1开始,您将不会处理任何双重组合。

代码语言:javascript
复制
$cachedCount = count($array);
for ($outer = 0; $outer < $cachedCount; $outer++){
  for ($inner = $outer+1; $inner< $cachedCount; $inner++){
    // process entries. no duplicates here. Only the ones that are dupplicates, 
    // but shouldn't be.
  }
}

即假设数组

代码语言:javascript
复制
0 -> "a"
1 -> "b"
2 -> "c"
3 -> "d"

它将采取以下步骤:

代码语言:javascript
复制
outer = 0; inner = 1; //a-b
outer = 0; inner = 2; //a-c
outer = 0; inner = 3; //a-d

outer = 1; inner = 2; //b-c
outer = 1; inner = 3; //b-d

outer = 2; inner = 3; //c-d

因此,检查所有组合,但不处理重复(a-cc-a)或普通组合(a-ab-b)。显然,对于两个元素,它将开始和结束比较0-1。(与执行2×2迭代的4次比较(1-11-22-12-2)相比,这是一次比较。

票数 1
EN

Stack Overflow用户

发布于 2014-04-08 15:44:06

可以使用索引来调整循环的大小:

代码语言:javascript
复制
<?php
$arr = array( '1', '2', '3', '4' );
for($a=0; $a<count($arr); $a++){
    for($b=0; $b<$a; $b++){
        echo "compare: ".$arr[$a]." ".$arr[$b].",\n";
    }
}

//Ouput
//compare: 2 1,
//compare: 3 1,
//compare: 3 2,
//compare: 4 1,
//compare: 4 2,
//compare: 4 3,

http://codepad.org/BdxzvTvj

请注意,虽然这是一个很好的解决方案,它只会提供50%的速度。有些算法上的变化可能会使这些收益相形见绌。

票数 0
EN

Stack Overflow用户

发布于 2014-04-08 15:45:28

也许是这样的:

代码语言:javascript
复制
foreach ($results as $p_id => $p_result) {
    foreach (array_slice($results, $p_id+1, NULL, true) as $c_id => $c_result) {
        if ($p_result['from'] < $c_result['to'] && $p_result['to'] > $c_result['from']) {
            $results[$p_id]['match'] = $c_id;
            break;
        }
    }

}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/22941583

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档