How do I find and count identical values in an array, then insert a node with: ‘count: (int)’ via PHP?

Viewed 119

I have a dynamic array of latitudes and longitudes, but I need to insert the count of identical values while eliminating the duplicates via PHP. So this...

Array (
    [0] => Array (
            [lat] => 40.7587979
            [lon] => -73.9623427
        )
    [1] => Array (
            [lat] => 39.8587028
            [lon] => -84.277025
        )
    [2] => Array (
            [lat] => 37.7647993
            [lon] => -122.4629897
        )
    [3] => Array (
            [lat] => 37.7647993
            [lon] => -122.4629897
        )
    [4] => Array (
            [lat] => 33.5125302
            [lon] => -117.6860507
        )
    [5] => Array (
            [lat] => 39.8587028
            [lon] => -84.277025
        )
)

...becomes this...

Array (
    [0] => Array (
            [lat] => 40.7587979
            [lon] => -73.9623427
            [count] => 1
        )
    [1] => Array (
            [lat] => 39.8587028
            [lon] => -84.277025
            [count] => 2
        )
    [2] => Array (
            [lat] => 37.7647993
            [lon] => -122.4629897
            [count] => 2
        )
    [3] => Array (
            [lat] => 33.5125302
            [lon] => -117.6860507
            [count] => 1
        )
)

I understand using array_count_values(), but that doesn't insert the new count values within each node. The use case would be a heatmap where the map is weighted based on the number of identical coordinates.

1 Answers

There are a few ways to approach this involving loops and conditionals, but array_count_values() works very well for large sets. Here's a loop that bundles array_count_values() with array_map() to:

  1. array_map() converts the lat,lng array pair of the original array into an array of string lat|lng
  2. array_count_values() counts the unique values of those lat|lng strings and returns them as array keys pointing to the count as values
  3. foreach loop iterates that array of lat|lng keyed counts and splits them back out into the output sub-arrays.

// To hold the new array
$out = [];

// Outer loop over the result from array_count_values()
foreach (array_count_values(array_map(function($l) {
    // Map function combines lat|lng
    return implode("|", $l);
  // The rest of the loop syntax...
  }, $original_array)) as $pair => $count) {

  // Split the counted array key back to individual lat,lng
  list($lat, $lng) = explode("|", $pair);

  // Put it all onto the output array
  $out[] = [
    'lat' => $lat,
    'lng' => $lng,
    'count' => $count
  ];
}

print_r($out);

Prints:

Array
(
    [0] => Array
        (
            [lat] => 40.7587979
            [lng] => -73.9623427
            [count] => 1
        )

    [1] => Array
        (
            [lat] => 39.8587028
            [lng] => -84.277025
            [count] => 2
        )

    [2] => Array
        (
            [lat] => 37.7647993
            [lng] => -122.4629897
            [count] => 2
        )

    [3] => Array
        (
            [lat] => 33.5125302
            [lng] => -117.6860507
            [count] => 1
        )

)

Note: One difference from your example output is that you retained the original outer array keys after discarding duplicates 0,1,2,4. This output is a fresh array numbering all outer keys sequentially 0,1,2,3. If you actually need to keep the original array keys, more will need to be done.

Working demonstration

Related