0

I have a multidimensional array containing arrays which each containing an artisan and closeness key.I want to merge multiple arrays if the same artisans to a single array with its closeness being the sum of the values of the closeness of the arrays it was merged from.

That is,this array:

Array
(
    [0] => Array
        (
            [artisan] => carpenter
            [closeness] => 0.8
        )

    [1] => Array
        (
            [artisan] => brick layer
            [closeness] => 0.4
        )

    [2] => Array
        (
            [artisan] => electrician
            [closeness] => 0.9
        )

    [3] => Array
        (
            [artisan] => carpenter
            [closeness] => 0.8
            [is_real] => 1
        )

    [4] => Array
        (
            [artisan] => brick layer
            [closeness] => 0.9
            [is_real] => 1
        )

)

Should become:

Array
(
    [0] => Array
        (
            [artisan] => carpenter
            [closeness] => 1.6 //0.8+0.8
        )

    [1] => Array
        (
            [artisan] => brick layer
            [closeness] => 1.3  //0.4+0.9
        )

    [2] => Array
        (
            [artisan] => electrician
            [closeness] => 0.9 //remains 0.9 because it is the only array with artisan value of electrician
        )

Thanks

  • Didn't you ask the same question already? I saw a similar question, and there were answers, but it seems to have been deleted. – Barmar May 22 '20 at 16:34
  • I am not a specialist on the subject, and there probably is a way to do this, but what I would do is I'll obtain the distinct `artisan` and initiate a new array with those. Then I would just run through new array using foreach and using the `artisan` value as index and run through the first array and just do the math. – Mihail Minkov May 22 '20 at 16:34
  • See also https://stackoverflow.com/questions/35473174/creating-one-array-from-another-array-in-php – Barmar May 22 '20 at 16:35
  • @Barmar Im sorry, I tried soo many things but none of them worked so I deleted them from my code – Out of the box May 22 '20 at 16:35
  • @Barmar Yes I asked the same question but I made a mistake so u gave me wrong answers and I was afraid that no ome elsr would answer it after seeing an answer already posted – Out of the box May 22 '20 at 16:38
  • Yeah, the previous question was about merging two arrays, this is about one array. – Barmar May 22 '20 at 16:39
  • See https://stackoverflow.com/questions/57852456/php-array-group-by-same-values-and-sum for summing by group. – Barmar May 22 '20 at 16:41

2 Answers2

0

Try out this loop

//create new array to hold values in the format you need
$new_array = [];

//loop through old array
foreach($old_array as $arr) {

    $artisan = $arr['artisan'];
    $closeness = $arr['closeness'];

    //check if `$artisan` key does not exists in `$new_array`
    if(!array_key_exists($artisan, $new_array)) {

        //create key in `$new_array` if it doesn't exist already
        //for this key, create an array containing the values in the format you need
        $new_array[$artisan] = [
            'artisan' => $artisan, 
            'closeness' => $closeness
        ];

    } else {

        //increase closeness in `$new_array` with key `$artisan` if key did already exist
        $new_array[$artisan]['closeness'] += $closeness;

    }

}

//replace keys which contain `$artisan` with sequential numbers, as per your expected output.
//if you don't do this, it will still work, but your array keys will be equal to the artisan type.
$new_array = array_values($new_array);
print_r($new_array);

Results:

Array
(
    [0] => Array
        (
            [artisan] => carpenter
            [closeness] => 1.6
        )

    [1] => Array
        (
            [artisan] => brick layer
            [closeness] => 1.3
        )

    [2] => Array
        (
            [artisan] => electrician
            [closeness] => 0.9
        )

)

If you remove the array_values() line, your result will look like this:

Array
(
    [carpenter] => Array
        (
            [artisan] => carpenter
            [closeness] => 1.6
        )

    [brick layer] => Array
        (
            [artisan] => brick layer
            [closeness] => 1.3
        )

    [electrician] => Array
        (
            [artisan] => electrician
            [closeness] => 0.9
        )

)
GrumpyCrouton
  • 8,486
  • 7
  • 32
  • 71
0

How about:

$results = array(); // create results array

foreach( $array as $k => $i ) {

    $found = false;

    foreach ( $results as $k => $r ) {

        if ( $r[ "artisan" ] == $i[ "artisan" ] ) {

            $results[ $k ][ "closeness" ] += $i[ "closeness" ];

            $found = true;

            break;

        }

    }

    if ( ! $found ) array_push( $results, $i );

}