简体   繁体   中英

Getting multiple specific key value pairs if exist in associate array

I want to convert my Associate Array into array based on certain criteria:

  • It should contain multiple column (Hence, can't user array_column in this case.)
  • It should ADD duplicate date
  • It should remove particular sub-array if NULL. ( array_filter )

Input:

array (
  0 => 
  array (
    'date' => "2019-03-31",
    'a' => '1',
    'b' => '1',
  ),
  1 => 
  array (
    'date' => "2019-04-02",   // If "SAME" date then ADD them
    'a' => '1',
    'b' => '1',
  ),
  2 => 
  array (
    'date' => "2019-04-02",   // If "SAME" date then ADD them
    'a' => '2',
    'b' => '1',
  ),
  3 => 
  array (
    'date' => "2019-04-10",
    'a' => '',                // If "NULL" then remove the particular sub-array
    'b' => '1',               
  ),
  4 => 
  array (
    'date' => "2019-04-18",
    'a' => '4',
    'b' => '10',
  ),
)


I've tried the following,

Although I was able to select multiple column in array but this is giving me:

  • "Duplicate" date.
  • And including sub-array which has "Null" value.
function colsFromArray(array $array, $keys)
{
    if (!is_array($keys)) $keys = [$keys];
    return array_map(function ($el) use ($keys) {
        $o = [];
        foreach($keys as $key){
            $o[$key] = isset($el[$key])?$el[$key]:false;
        }
        return $o;
    }, $array);
}


$result =  colsFromArray($arr, array("date", "a"));


Required Output:

array (
  0 => 
  array (
    'date' => "2019-03-31",
    'a' => '1',
  ),
  1 => 
  array (
    'date' => "2019-04-02",
    'a' => '3',
  ),
  2 => 
  array (
    'date' => "2019-04-18",
    'a' => '4',
  ),
)

You could try something like this:

function colsFromArray(array $array, $keys)
{
    if (!is_array($keys)) $keys = [$keys];

    $returnArray = [];

    foreach($array as $in){
        foreach($keys as $key){

            //Check if the key already has a value
            if(isset($returnArray[$in['date']][$key]) && is_numeric($returnArray[$in['date']][$key])){
                $returnArray[$in['date']][$key] += $in[$key];
            }
            //If the key is empty, continue
            elseif(empty($in[$key])){
                continue;
            }
            //If value is to be set, set date as well
            else{
                $returnArray[$in['date']]['date'] = $in['date'];
                $returnArray[$in['date']][$key] = $in[$key];
            }
        }
    }

    //Return array after resetting indexes and removing empty entries
    return array_values(array_filter($returnArray));
}

The way that you are passing in the array of columns to your customer function is ambiguous about what should be used to group by and what should be summed. OR if you will never have more than two elements in your 2nd parameter, then your custom function lacks flexibility.

Notice how @SverokAdmin's answer has date hardcoded in the logic, but there is no guarantee that this column name will always exist in the first parameter $array . Ergo, the utility function cannot be reliably used as a utility function.

Consider this custom function which provides your desired result, but allows more meaningful parameter declarations. My snippet allows you to group by one or more column, keep one or more columns in the subarrays, and specify which column should be summed. I cannot make the last column iterable because you state that if a column is missing a value, it should be omitted from the result. In other words, your desired result is unknown if you wanted to sum a and b , but one of the a values was empty.

Code: ( Demo )

function colsFromArray(array $array, $groupBy, $keepables, $summable): array
{
    $groupBy = (array)$groupBy;
    $keepables = (array)$keepables;
    // cannot make $summable iterable type because question is unclear on the desired outcome when one of the columns is empty

    return array_values(
        array_reduce(
            $array,
            function ($result, $row) use($groupBy, $keepables, $summable) {
                $uniqueKey = [];
                foreach ($groupBy as $col) {
                    $uniqueKey[] = $row[$col];
                }
                $uniqueKey = implode('_', $uniqueKey);
                
                if (!$row[$summable]) {
                    return $result;
                }
                
                foreach ($keepables as $keepable) {
                    $result[$uniqueKey][$keepable] = $row[$keepable];
                }
                $result[$uniqueKey][$summable] = ($result[$uniqueKey][$summable] ?? 0) + $row[$summable];
                return $result;
            },
            []
        )
    );
}

var_export(
    colsFromArray($arr, 'date', 'date', 'a')
);

Output:

array (
  0 => 
  array (
    'date' => '2019-03-31',
    'a' => 1,
  ),
  1 => 
  array (
    'date' => '2019-04-02',
    'a' => 3,
  ),
  2 => 
  array (
    'date' => '2019-04-18',
    'a' => 4,
  ),
)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM