对多维数组的行进行分组,并在每个组内形成逗号分隔的值

问题描述 投票:0回答:6

我想合并具有相同类别 id 和问题 id 的数组。

输入示例:

$array = [
    [
        'category_id' => 1,
        'question_id' => 1,
        'option_id' => 2,
        'title' => 'Do you wear glasses?',
        'answer' => 'no'
    ],
    [
        'category_id' => 1,
        'question_id' => 2,
        'option_id' => 3,
        'title' => 'Your hobbies ?',
        'answer' => 'movies'
    ],
    [
        'category_id' => 1,
        'question_id' => 4,
        'option_id' => 8,
        'title' => 'what is your status?',
        'answer' => 'single'
    ],
    [
        'category_id' => 1,
        'question_id' => 2,
        'option_id' => 1,
        'title' => 'Your hobbies ?',
        'answer' => 'travel'
    ],
];

第二个和第四个数组包含相同的问题(相同的类别 ID 和相同的问题 ID),所以我希望将它们的答案值合并在一起作为逗号分隔的字符串。

想要的结果:

Array(
[0] => Array
    (
        [category_id] => 1
        [question_id] => 1
        [option_id] => 2
        [title] => Do you wear glasses?
        [answer] => no
    )

[1] => Array
    (
        [category_id] => 1
        [question_id] => 2
        [option_id] => 3
        [title] => Your hobbies ?
        [answer] => movies,travel
    )

[2] => Array
    (
        [category_id] => 1
        [question_id] => 4
        [option_id] => 8
        [title] => what is your status?
        [answer] => single
    )
) 

分组时选项 id 和标题被覆盖是可以的,因为我没有使用选项 id 并且每个组中的标题值都是相同的。

php arrays multidimensional-array grouping delimited
6个回答
0
投票

也许这样的东西可以工作,不确定是否有更好的方法:

new_array=array();
foreach($source_array as $e){
     $insert=1;
     foreach($new_array as $n)
         if(array_search($e['title'], $n)==false){
              $n['answer'].=", ".$e['answer'];
              $insert=0;   
         }
     }
     if($insert){
         $new_array[]=$e;
     }
}

0
投票

示例数组

Array
(
[0] => Array
    (
        [category_id] => 1
        [question_id] => 1
    )

[1] => Array
    (
        [category_id] => 2
        [question_id] => 2
    )

[2] => Array
    (
        [category_id] => 1
        [question_id] => 1
    )

)

你可以做这样的事情作为插图

// Define the array to work on
$array = array( array( 'category_id' => 1, 'question_id'=> 1), array( 'category_id' => 2, 'question_id' => 2),  array( 'category_id' => 1, 'question_id' => 1));

// Initialize the result array containing only unique question_id/category_id combinations
$unique_array = array();

foreach ($array as $key) {
    if (!count($unique_array)) {
        $unique_array[] = $key;
    } else {
        $unique = 1;
        foreach ($unique_array as $check) {
            if ( $check['category_id'] ==  $key['category_id'] && $check['question_id'] == $key['question_id'] ) {
                $unique = 0;
            }
        }
        if ( $unique ) {
            $unique_array[] = $key;
        }
    }
}

print_r($unique_array);

最后一个 print_r 的输出将是

Array
(
[0] => Array
    (
        [category_id] => 1
        [question_id] => 1
    )

[1] => Array
    (
        [category_id] => 2
        [question_id] => 2
    )

)

0
投票

我问顺序是否重要的原因是,如果不重要,你可以先对数组进行排序,然后只将每个数组与其前一个兄弟姐妹进行比较:

$source=array(array("cat_id"=>1,"ques_id"=>1,"opt_id"=>2,"title"=>"cid:1, qid:1, oid:2","answer"=>"whatever"),array("cat_id"=>1,"ques_id"=>2,"opt_id"=>3,"title"=>"cid:1, qid:2, oid:3","answer"=>"whatever"),array("cat_id"=>1,"ques_id"=>4,"opt_id"=>8,"title"=>"cid:1, qid:4, oid:8","answer"=>"whatever"),array("cat_id"=>1,"ques_id"=>2,"opt_id"=>1,"title"=>"cid:1, qid:2, oid:1","answer"=>"whtvr"));
print_r($source); // just to debug

usort($source,function($a,$b){
    if($a["cat_id"]<$b["cat_id"])
        return -1;
    elseif($a["cat_id"]>$b["cat_id"])
        return 1;
    elseif($a["ques_id"]<$b["ques_id"])
        return -1;
    elseif($a["ques_id"]>$b["ques_id"])
        return 1;
    elseif($a["opt_id"]<$b["opt_id"])
        return -1;
    elseif($a["opt_id"]>$b["opt_id"])
        return 1;
    else
        return 0;
});

$source=array_reduce($source,function(&$a,$b){
    if(empty($a))
    {
        $a=array($b);
    }
    else
    {
        $cache=array_pop($a);
        if($cache["cat_id"]==$b["cat_id"] && $cache["ques_id"]==$b["ques_id"])
        {
            $cache["answer"].=", ".$b["answer"];
            $a[]=$cache;
        }
        else
        {
            $a[]=$cache;
            $a[]=$b;
        }
    }
    return $a;
},array());
print_r($source);

输出:

// first print_r
Array
(
    [0] => Array
        (
            [cat_id] => 1
            [ques_id] => 1
            [opt_id] => 2
            [title] => cid:1, qid:1, oid:2
            [answer] => whatever
        )

    [1] => Array
        (
            [cat_id] => 1
            [ques_id] => 2
            [opt_id] => 3
            [title] => cid:1, qid:2, oid:3
            [answer] => whatever
        )

    [2] => Array
        (
            [cat_id] => 1
            [ques_id] => 4
            [opt_id] => 8
            [title] => cid:1, qid:4, oid:8
            [answer] => whatever
        )

    [3] => Array
        (
            [cat_id] => 1
            [ques_id] => 2
            [opt_id] => 1
            [title] => cid:1, qid:2, oid:1
            [answer] => whtvr
        )

)
// second print_r
Array
(
    [0] => Array
        (
            [cat_id] => 1
            [ques_id] => 1
            [opt_id] => 2
            [title] => cid:1, qid:1, oid:2
            [answer] => whatever
        )

    [1] => Array
        (
            [cat_id] => 1
            [ques_id] => 2
            [opt_id] => 1
            [title] => cid:1, qid:2, oid:1
            [answer] => whtvr, whatever
        )

    [2] => Array
        (
            [cat_id] => 1
            [ques_id] => 4
            [opt_id] => 8
            [title] => cid:1, qid:4, oid:8
            [answer] => whatever
        )

)

请注意,您在评论中指出

option_id
无关紧要,所以我没有替换它;如果需要,您也可以在
array_reduce
内的匿名函数中替换它。


0
投票
$data = array();

//$new is the array in which you have data originally
foreach($new as $arrayK => $arrayV){
    if(!isset($data[$arrayV['category_id']][$arrayV['question_id']]))
        $data[$arrayV['category_id']][$arrayV['question_id']] = $arrayV;
    else{
        $option = $data[$arrayV['category_id']][$arrayV['question_id']]['option_id'] . ',' . $arrayV['option_id'];
        $data[$arrayV['category_id']][$arrayV['question_id']]['option_id'] = $option;

        $answer = $data[$arrayV['category_id']][$arrayV['question_id']]['answer'] . ',' . $arrayV['answer'];
        $data[$arrayV['category_id']][$arrayV['question_id']]['answer'] = $answer;
    }
}

$data 将具有上述格式的所需数据
答案和选项都以逗号分隔


0
投票
foreach($arr as $k=>$a)
{
    $common[$k] = search($arr,'category_id',$a['category_id'],'question_id',$a['question_id']);
    $answers = array_map(function($item) { return $item['answer']; }, $common[$k]);
    $options = array_map(function($item) { return $item['option_id']; }, $common[$k]);
    foreach($common[$k] as $temp)
    {
        $finalAns = $temp;
        $finalAns['answer'] = implode(",",$answers);
        $finalAns['option_id'] = implode(",",$options);
    }
    $final[] = $finalAns;
}

$final = array_map("unserialize", array_unique(array_map("serialize", $final)));
echo "<pre>";
print_r($final);

将以下函数放入您的常用函数文件或同一文件中。

function search($array, $key, $value, $key1, $value1)
{
    $results = array();

    if (is_array($array))
    {
        if (isset($array[$key]) && $array[$key] == $value && isset($array[$key1]) && $array[$key1] == $value1)
        {
            $results[] = $array;
        }

        foreach ($array as $subarray)
            $results = array_merge($results, search($subarray, $key, $value,$key1,$value1));
    }

    return $results;
}

你的输出将是

数组 ( [0] => 数组 ( [category_id] => 1 [问题 ID] => 1 [选项 ID] => 2 [title] => 你戴眼镜吗? [答案] => 否 )

[1] => Array
    (
        [category_id] => 1
        [question_id] => 2
        [option_id] => 3,1
        [title] => Your hobbies ?
        [answer] => movies,travel
    )

[2] => Array
    (
        [category_id] => 1
        [question_id] => 4
        [option_id] => 8
        [title] => what is your status?
        [answer] => single
    )


0
投票

没有理由出现复杂的逻辑或多个循环。

每个组都需要有一个唯一的标识符。 尽管提问者指出

question_id
就足够了,但您可以通过将
question_id
category_id
组合为分隔字符串来保证唯一性。 将数据推入结果数组时,使用此“复合标识符”作为第一级键。

当再次遇到复合键时),则不要同时保存所有数据——仅将数据附加到所需的元素。

完成迭代后,重新索引结果数组以删除临时复合键(如果您愿意)。

代码:(演示

$result = [];
foreach ($array as $row) {
    $compositeKey = $row['category_id'] . '_' . $row['question_id'];
    if (!isset($result[$compositeKey])) {
        $result[$compositeKey] = $row;
    } else {
        $result[$compositeKey]['answer'] .= ",{$row['answer']}";
    }
}
var_export(array_values($result));

P.s.通常,最好形成子数组而不是逗号分隔的字符串。 子数组可以更好地访问各个值并提高表示的灵活性。 如果您改变了如何呈现值的想法,则需要删除或替换逗号并打印其他内容。 省去麻烦,将演示留给您的(视图)演示循环,并完全按照您的意愿内爆子数组值。


考虑到 Laravel 在 PHP 项目中的流行,我还将添加一个 Laravel 解决方案,该解决方案会牺牲性能以实现可链接性。 该脚本假设输入数组通过

collect()
传递成为集合对象。 PHPize 演示

var_export(
    $collection
    ->groupBy(fn($item) => $item['category_id'] . '_' . $item['question_id'])
    ->map(fn($group) => collect($group->first())->put('answer', $group->pluck('answer')->implode(', ')))
    ->values()
    ->toArray()
);

请参阅这些非常相关的答案,它也实现了链式 Laravel 方法。

© www.soinside.com 2019 - 2024. All rights reserved.