1

I have two sets of arrays like this for example.

$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;

The size of two arrays could be different of course. $Arr1 has coefficient of 0.7 and $Arr2 has coefficient of 0.3. I need to calculate following formula

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

where $Arr1['uid']=$Arr2['uid']. So when $Arr1['uid'] doesn't exists in $Arr2 then we need to omit $Arr2 and vice versa.
And, here is an algorithm I am using now.

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";
    }
}

The question is how can I optimize this algorithm? Can you offer other better solution for this problem?
Thank you.

4
  • Can this be done at SQL level? Looks to me like that'd be the most ideal solution. Commented Jun 18, 2010 at 9:54
  • I am afraid it is impossible with the current DB Design I have. Commented Jun 18, 2010 at 10:03
  • 1
    The order of your keys seems unintuitive - $Arr1['uid'][0] correlates to $Arr1['weight'][0]. This practice could easily become hard to maintain (ensuring you always add a weight for every uid). It may make more sense to store your data using $Arr1[] = array('uid'=>'user1', 'weight'=>1) or even, if uid is meant to be a unique key for the array -- $Arr1['user1'] = array('uid'=>'user1', 'weight' => 1); (I am assuming there are also more columns of data than just 'weight') Commented Jun 18, 2010 at 11:31
  • @gnarf. You are completely right. I wanted to present arrays in that way but forgot to change it. Thank you. Commented Jun 18, 2010 at 11:35

4 Answers 4

3

Due to the way you have your arrays organized, you can use array_combine($keys, $values) to assemble $Arr1 and $Arr2 into associative arrays using keys from ['uid'] and values from ['weight']. Using the associative arrays simplifies the calculation quite a bit:

$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";
}

Results Compared

Your code:

user 1 has found on 0 and RES=1.6
user 2 has found on 3 and RES=7.6
user 3 has not found and RES=3.5
user 1 has found somewhere
user 4 has not found and RES=6
user 5 has not found and RES=4.5
user 2 has found somewhere

My Code:

user 1 final weight: 1.6
user 2 final weight: 7.6
user 3 final weight: 3.5
user 4 final weight: 6
user 5 final weight: 4.5
Sign up to request clarification or add additional context in comments.

3 Comments

But I think, when you are calling array_merge, "weight" of two identical "uid"s will be merged, right? What happens if $Arr1['user1']['weight']=1; $Arr2['user1']['weight']=2?
I elaborated on your answer quite a bit, +1 for the brilliant array_combine() - Please, feel free to roll back my edits if you don't like what I've done.
@gnarf: thank you, I don't see why I would roll back, it's a better and more complete solution. Thank you :)
1

It would be easier if you used the user as the array key. Something like this:

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

Then you can use array_diff_assoc and array_intersect_assoc to find out what which elements are in and not in the other array.

Comments

0

You can impelement binary searching in O(log(n)) complexity insead of your linear O(n) array_search. But you must before create tree from this or sort this array in O(n*log(n)).

More information about binary searching you can find at:

Comments

-2

Firstly you should intialize the array as the associative array. Calculations would be more easily.

1 Comment

it is an associative array. I think you mean to use a different key for the arrays.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.