如何合并具有相似键的数组数组中的元素仅相差一个键值

时间:2013-03-07 03:18:28

标签: php arrays function loops merge

我正在使用PHP,并且有一个类似于以下内容的数组:

Array(
    [0] => Array(
           [id]  =>1,
           [name]=>"edward",
           [asset]=>"somesong.mp3"
           ),
    [1] => Array(
           [id]  =>1,
           [name]=>"edward",
           [asset]=>"somemovie.mov"
           ),
    [2] => Array(
           [id]  =>2,
           [name]=>"sally",
           [asset]=>"anothersong.mp3"
           ),
    [3] => Array(
           [id]  =>2,
           [name]=>"sally",
           [asset]=>"anothermovie.mov"
           ),
...
)

如您所见,它们在主数组中的每个元素之间是相似的,只是[asset]键的值不同。我想合并主数组中的元素,以便每个[asset]的两个值都保存在新元素中,就像这样

FinalArray(
    [0] => Array(
           [id]  =>1,
           [name]=>"edward",
           [song]=>"somesong.mp3",
           [movie]=>"somemovie.mov"
           ),
    [1] => Array(
           [id]  =>2,
           [name]=>"sally",
           [song]=>"anothersong.mp3",
           [movie]=>"anothermovie.mov"
           )
...
)

我开始使用结构

使用内部和外部foreach()循环的组合进行探索
// $person and $person02 are copies of the same array
foreach($person as $key=>$value){
    // grab an element in this loop
    $currElement=$person[$key];
    foreach($person2 as $key2=>$value2){
        $currElement2=$person2[$key2];
        // compare $currElement to $currElement2
        if($currElement['id']==$currElement2['id']){
            // determine if [asset] is an mp3 or mov
            $currAsset2=$currElement2['asset'];
            $currAsset =$currElement['asset'];

            $ext = substr(strrchr($currAsset,'.'),1)
            if($ext=='mp3'){ 
                // then we have a song and should store it
                $song=$currAsset['asset'];
                $movie=$currAsset2['asset'];
            }else{
                //  switch sides if you like
                $song=$currAsset2['asset'];
                $movie=$currAsset['asset'];
            }
        }

        // create a new array and add it to the result array
        $newArrEl = array(
            'id'   =>$currElement['id'],
            'name' =>$currElement['id'],
            'song' => $song,
            'movie' => $movie
        );
        $resultArray.push(); // add to final array
    }
}
}

问题是,我探索了一堆php数组函数的组合,似乎无法让它完全正确。所以我希望有人在这里帮我解决这个问题。如何将原始数据与类似的值合并到要添加到最终数组的较新元素中?

2 个答案:

答案 0 :(得分:0)

看起来你的主要标识符是id,我会创建一个id为关键字的目标数组,并只迭代原始数组一次,如下所示:

<?php 

$original_array = array(
    array(
        'id' => 1,
        'name' => 'edwards',
        'asset' => "somesong.mp3"
    ),
    array(
        'id' => 1,
        'name' => 'edwards',
        'asset' => "somemovie.mov"
    ),
    array(
        'id' => 2,
        'name' => 'sally',
        'asset' => "anothersong.mp3"
    ),
    array(
        'id' => 2,
        'name' => 'sally',
        'asset' => "anothermovie.mov"
    )
);

$result = array();

$fields_map = array(
    '/\.mp3$/iS' => 'song',
    '/\.mov$/iS' => 'movie'
);

foreach($original_array as $item)
{
    $id = $item['id'];

    if (!isset($result[$id]))
    {
        // initial population
        $result[$id] = array(
            'id' => $id,
            'name' => $item['name']
        );
    }

    if (isset($item['asset']))
    {
        foreach($fields_map as $re => $field_name)
        {
            if (preg_match($re, $item['asset']))
            {
                $result[$id][$field_name] = $item['asset'];
                break;
            }
        }
    }
}

var_dump($result);

注意:我在field_map上使用regexp而不是文件扩展名上的简单hashmap,因为我假设您可能需要更多扩展来支持相同的字段(例如mp3,ogg,wav,flac all mapping to田野'歌')。正则表达式可以很容易地添加更多字段。

答案 1 :(得分:0)

试试这个:

$array = array(
    array(
        'id' => 1,
        'name' => 'edwards',
        'asset' => "somesong.mp3"
    ),
    array(
        'id' => 1,
        'name' => 'edwards',
        'asset' => "somemovie.mov"
    ),
    array(
        'id' => 2,
        'name' => 'sally',
        'asset' => "anothersong.mp3"
    ),
    array(
        'id' => 2,
        'name' => 'sally',
        'asset' => "anothermovie.mov"
    )
);

$res   = array();

foreach($array as $val){
   $res[$val['id']]['id'] =  $val['id'];
   $res[$val['id']]['name'] =  $val['name'];
   if(preg_match('/mp3$/',$val['asset'])){
    $res[$val['id']]['song'] =  $val['asset'];
   }
   if(preg_match('/mov$/',$val['asset'])){
    $res[$val['id']]['movie'] =  $val['asset'];
   }
}
$res  = array_values($res);

echo "<pre>";
print_r($res);