b.doe
b.doe

Reputation: 134

Get lowest key - array value in multidimensional array PHP

So, I got array that looks something like this:

[65]=>
  array(2) {
    [0]=>
    array(2) {
      ["p"]=>
      float(234)
      ["sp"]=>
      float(234)
    }
    [1]=>
    array(2) {
      ["p"]=>
      float(53)
      ["sp"]=>
      float(5)
    }
    [2]...
    [3]...

  }

The idea is to go through each of 0 - N values of key 65 array, and only keep one with smallest "p", others should be removed / filtered out.

This should be done in PHP. Anyone has any idea?

I tried something like this:

$array = array_filter($array, function ($value, $key) use ($a) {
   return $a['p'] <= $value['p'];
}, ARRAY_FILTER_USE_BOTH);

where $value is 1 of elements inside 65 keyed-array and $a is current pair that is being added dynamically. So when ever its added, I go through existing elements and if its lowest, it should stay, and others get instant filtered out, but if its higher, it should automatically be filtered out.

Thank you!

Upvotes: 2

Views: 528

Answers (3)

The fourth bird
The fourth bird

Reputation: 163217

If have more than 1 nested levels, you might also use a recursive approach checking the value of p, keeping the array with the lowest value.

$arrays = [
    65 => [
        ["p" => 234, "sp" => 234],
        [
            ["p" => 53,"sp" => 5],
            [
                ["p" => 54,"sp" => 1],
                ["p" => 53,"sp" => 7],
            ]
        ], [
            "p" => 255,
            "sp" => 235
        ],
    ]
];

function loop($array, &$coll = [], &$min = null)
{
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            loop($value, $coll, $min);
        } elseif ($key === "p") {
            if ($min === null) $min = $value;
            if ($min > $value) {
                $coll = [$array];
                $min = $value;
                continue;
            }
            if($value === $min) $coll[] = $array;
        }
    }
    return $coll;
}

$arrays[65] = loop($arrays[65]);
var_dump($arrays);

Output

array(1) {
  [65]=>
  array(2) {
    [0]=>
    array(2) {
      ["p"]=>
      int(53)
      ["sp"]=>
      int(5)
    }
    [1]=>
    array(2) {
      ["p"]=>
      int(53)
      ["sp"]=>
      int(7)
    }
  }
}

See another php demo.

Upvotes: 0

ArSeN
ArSeN

Reputation: 5248

You can use array_reduce() to get the lowest "p"-value:

$arr = [
    65 => [
        ["p" => 234, "sp" => 234],
        ["p" => 53, "sp" => 5],
        ["p" => 530, "sp" => 5],
    ]
];

function getLowestKey($carry, $item) {
    if ($item['p'] < $carry || !$carry) {
        $carry = $item['p'];
    }
    return $carry;
}

$lowestKey = array_reduce($arr[65], 'getLowestKey');
var_dump($lowestKey); // int(53)

Edit:

I just noticed there is a second part to your question, sorry about that. Once you found out the "lowest p" you can then just filter the array with that knowledge:

$lowestPs = array_filter($arr[65], function($item) use ($lowestKey) {
    return $item['p'] == $lowestKey;
});

var_dump($lowestPs);
/*
array(2) {
  [1]=>
  array(2) {
    ["p"]=>
    int(53)
    ["sp"]=>
    int(5)
  }
  [2]=>
  array(2) {
    ["p"]=>
    int(53)
    ["sp"]=>
    int(5)
  }
}
*/

This solution works even if multiple entries have the same lowest "p" value (like 53 in the above example), all of those will stay.

Upvotes: 2

berend
berend

Reputation: 631

Use array_column() to do an array_multisort() on the 'p' value for the records inside key 65.

<?php
$col = 'p'; // set the column you want to order on
$column = array_column($arr[65], $col);
array_multisort($column, SORT_ASC, $arr[65]);
$arr[65] = $arr[65][0]; // only keep the record with lowest 'p' value

demo

Upvotes: 2

Related Questions