【问题标题】:How to optimize this algorithm?如何优化这个算法?
【发布时间】:2011-03-05 08:36:36
【问题描述】:

例如,我有两组这样的数组。

$Arr1['uid'][]='user 1'; $Arr1['weight'][]=1;
$Arr1['uid'][]='user 2'; $Arr1['weight'][]=10;
$Arr1['uid'][]='user 3'; $Arr1['weight'][]=5;

$Arr2['uid'][]='user 1'; $Arr2['weight'][]=3;
$Arr2['uid'][]='user 4'; $Arr2['weight'][]=20;
$Arr2['uid'][]='user 5'; $Arr2['weight'][]=15;
$Arr2['uid'][]='user 2'; $Arr2['weight'][]=2;

当然,两个数组的大小可以不同。 $Arr1 的系数为 0.7,$Arr2 的系数为 0.3。我需要计算以下公式

$result=$Arr1['weight'][$index]*$Arr1Coeff+$Arr2['weight'][$index]*$Arr2Coeff;

在哪里$Arr1['uid']=$Arr2['uid']。因此,当$Arr1['uid'] 不存在于$Arr2 中时,我们需要省略$Arr2,反之亦然。
而且,这是我现在正在使用的算法。

foreach($Arr1['uid'] as $index=>$arr1_uid){
    $pos=array_search($arr1_uid, $Arr2['uid']);
    if ($pos===false){
        $result=$Arr1['weight'][$index]*$Arr1Coeff;
        echo "<br>$arr1_uid has not found and RES=".$result;
    }else{
        $result=$Arr1['weight'][$index]*$Arr1Coeff+$Arr2['weight'][$pos]*$Arr2Coeff;
        echo "<br>$arr1_uid has found on $pos and RES=".$result;
    }
}

foreach($Arr2['uid'] as $index=>$arr2_uid){
    if (!in_array($arr2_uid, $Arr1['uid'])){
        $result=$Arr2['weight'][$index]*$Arr2Coeff;
        echo "<br>$arr2_uid has not found and RES=".$result;
    }else{
        echo "<br>$arr2_uid has found somewhere";
    }
}

问题是如何优化这个算法?你能为这个问题提供其他更好的解决方案吗?
谢谢。

【问题讨论】:

  • 这可以在 SQL 级别完成吗?在我看来,这将是最理想的解决方案。
  • 我目前的数据库设计恐怕是不可能的。
  • 键的顺序似乎不直观 - $Arr1['uid'][0]$Arr1['weight'][0] 相关。这种做法很容易变得难以维护(确保您始终为每个 uid 添加权重)。使用$Arr1[] = array('uid'=&gt;'user1', 'weight'=&gt;1) 存储数据可能更有意义,甚至,如果uid 是数组的唯一键——$Arr1['user1'] = array('uid'=&gt;'user1', 'weight' =&gt; 1);(我假设还有更多的数据列而不仅仅是“权重”) ')
  • @gnarf。你是完全正确的。我想以这种方式呈现数组,但忘记更改它。谢谢。

标签: php algorithm arrays optimization


【解决方案1】:

首先,您应该将数组初始化为关联数组。计算会更容易。

【讨论】:

  • 它是一个关联数组。我认为您的意思是对数组使用不同的键。
【解决方案2】:

由于您组织数组的方式,您可以使用array_combine($keys, $values)$Arr1$Arr2 组合成关联数组,使用来自['uid'] 的键和来自['weight'] 的值。使用关联数组可以大大简化计算:

$combi1 = array_combine($Arr1['uid'], $Arr1['weight']);
$combi2 = array_combine($Arr2['uid'], $Arr2['weight']);

// loop through the keys from both arrays
foreach (array_keys($combi1+$combi2) as $uid) {
    // use the value from $combi1, or 0 if it isn't set
    $value1 = isset($combi1[$uid]) ? $combi1[$uid] : 0;
    // use the value from $combi2, or 0 if it isn't set
    $value2 = isset($combi2[$uid]) ? $combi2[$uid] : 0;
    // calculate our final weight
    $result = $value1 * $Arr1Coeff + $value2 * $Arr2Coeff;
    echo "<br>$uid final weight: ".$result."\n";
}

比较结果

您的代码:

用户 1 在 0 上找到并且 RES=1.6
用户 2 在 3 上找到并且 RES=7.6
用户 3 未找到且 RES=3.5
用户 1 在某处找到
未找到用户 4 且 RES=6
用户 5 未找到且 RES=4.5
用户 2 找到了某个地方

我的代码:

用户 1 最终体重:1.6
用户 2 最终体重:7.6
用户 3 最终体重:3.5
用户 4 最终体重:6
用户 5 最终体重:4.5

【讨论】:

  • 但是我认为,当您调用array_merge 时,两个相同“uid”的“权重”将被合并,对吧?如果 $Arr1['user1']['weight']=1; 会发生什么? $Arr2['user1']['weight']=2?
  • 我详细阐述了您的回答,为出色的array_combine() +1 - 如果您不喜欢我所做的,请随时回滚我的编辑。
  • @gnarf:谢谢,我不明白我为什么要回滚,这是一个更好、更完整的解决方案。谢谢你:)
【解决方案3】:

如果您使用用户作为数组键会更容易。像这样的:

$Arr1['user 1'] => array('weight'=>1);
$Arr1['user 2'] => array('weight'=>10);
...

然后您可以使用 array_diff_assoc 和 array_intersect_assoc 找出哪些元素在另一个数组中而不在另一个数组中。

【讨论】:

    【解决方案4】:

    您可以在O(log(n)) 复杂性中引入二分搜索,而不是线性O(n) array_search。但是您必须在从这里创建树或在O(n*log(n)) 中对这个数组进行排序之前。

    您可以在以下位置找到有关二分搜索的更多信息:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-15
      • 2021-09-14
      相关资源
      最近更新 更多