【问题标题】:PHP: how to merge one associative array into a sub-array of another multidimensional arrayPHP:如何将一个关联数组合并到另一个多维数组的子数组中
【发布时间】:2016-10-19 21:51:03
【问题描述】:

我有一个平面结果集,在 JSON 中看起来像这样:

[{
    "LineItemNo": "1",
    "SolNo": "SPE8E7-15-T-1379",
    "St": "O",
    "PartNo": "F13DBX\/SPX35\/4P",
    "UnitPrice": "1.890"
}, {
    "LineItemNo": "1",
    "SolNo": "SPE8E7-15-T-1379",
    "St": "O",
    "PartNo": "CF13DD\/E\/835",
    "UnitPrice": "1.920"
}, {
    "LineItemNo": "1",
    "SolNo": "SPE8E7-15-T-1379",
    "St": "O",
    "PartNo": "QT13\/35-4",
    "UnitPrice": "1.770"
}, {
    "LineItemNo": "2",
    "SolNo": "SPE8E7-15-T-4309",
    "St": "O",
    "PartNo": "F13DBX\/SPX35\/4P",
    "UnitPrice": "1.890"
}, {
    "LineItemNo": "2",
    "SolNo": "SPE8E7-15-T-4309",
    "St": "O",
    "PartNo": "CF13DD\/E\/835",
    "UnitPrice": "1.920"
}, {
    "LineItemNo": "2",
    "SolNo": "SPE8E7-15-T-4309",
    "St": "O",
    "PartNo": "QT13\/35-4",
    "UnitPrice": "1.770"
}]

我想改成这样:

{
    "data": [{
        "LineItemNo": "1",
        "SolNo": "SPE8E7-15-T-1379",
        "St": "O",
        "Parts": [{
            "PartNo": "F13DBX\/SPX35\/4P",
            "UnitPrice": "1.890"
        }, {
            "PartNo": "CF13DD\/E\/835",
            "UnitPrice": "1.920"
        }, {
            "PartNo": "QT13\/35-4",
            "UnitPrice": "1.770"
        }]
    }, {
        "LineItemNo": "2",
        "SolNo": "SPE8E7-15-T-4309",
        "St": "O",
        "Parts": [{
            "PartNo": "F13DBX\/SPX35\/4P",
            "UnitPrice": "1.890"
        }, {
            "PartNo": "CF13DD\/E\/835",
            "UnitPrice": "1.920"
        }, {
            "PartNo": "QT13\/35-4",
            "UnitPrice": "1.770"
        }]
    }]
}

我尝试了很多方法,但我无法找到一种方法来遍历源数组,在此过程中创建一个 Parts 数组,然后在后续迭代中将值插入该数组。我想做的是迭代源数组,检查$row['LineItemNo'] 值,如果它自上次迭代以来发生了变化,则创建一个新的顶级数组对象。如果没有,则创建一个新元素 Parts 数组。

我的基本代码如下所示(我意识到 mysql 已被 mysqli 或 PDO 弃用,但我暂时坚持使用它):

$result = mysql_query($query) or die(mysql_error());
$rs = array();
$rsParts = array();
while($row = mysql_fetch_array($result))
{
    if (!isset($ln) || $row['LineItemNo'] != $ln)
    {
        $ln = $row['LineItemNo'];
        $rs[data][] = array('LineItemNo' => $row['LineItemNo'], 'SolNo' => $row['SolNo'], 'St' => $row['St']);
        $rs[data][parts] = array();
    }
    array_push($rs[data][parts], array('PartNo' => $row['PartNo'], 'UnitPrice' => $row['UnitPrice']));
}

这是一个好的开始,但它只给了我第一个元素中的部分,像这样:

{
    "data": {
        "0": {
            "LineItemNo": "1",
            "SolNo": "SPE8E7-15-T-1379",
            "St": "O"
        },
        "parts": [{
            "PartNo": "F13DBX\/SPX35\/4P",
            "UnitPrice": "1.890"
        }, {
            "PartNo": "CF13DD\/E\/835",
            "UnitPrice": "1.920"
        }, {
            "PartNo": "QT13\/35-4",
            "UnitPrice": "1.770"
        }],
        "1": {
            "LineItemNo": "2",
            "SolNo": "SPE8E7-15-T-4309",
            "St": "O"
        }
    }
}

我认为您不能以这种方式重新初始化数组。我尝试在 LineItemNo 更改时取消设置它,但这会将所有 Parts 元素变成顶级元素。我尝试只在开头使用is_array 初始化数组,但这会将所有部分放入第一个顶级元素(第一个中有六个部分,第二个没有)。

那么,做我想做的事情的正确方法是什么?

编辑:问题的解决方案是首先通过此代码发送结果集($result):

$array = array();
while($r = mysql_fetch_assoc($result))
{
    $array[] = $r;
}

然后从那里使用 SML 的解决方案。

【问题讨论】:

    标签: php multidimensional-array associative-array


    【解决方案1】:

    假设任何给定的LineItemNo 总是与相同的SolNoSt 配对,您可以将每一行的LineItemNo 传递给一个函数来检查该值是否存在于结果的子数组中数组$rs

    如果LineItemNo$rs 中不存在,则创建一个新的$rs 的第一级子数组,并且包含parts info 的第二级子数组也将添加为第一级数组的子数组元素parts

    如果LineItemNo 确实存在,则只需将parts info 添加为第一级数组元素parts 的子数组。

    由于您希望在输出中使用顶级数组 ['data'],因此在此阶段不执行任何操作。
    我将其从流程中剥离出来,而是在最后阶段将 $rs 添加到 $output['data'] 以形成您需要的输出。

    $rs=array();
    $counter=0;
    while($r = mysql_fetch_assoc($results)) {
        $array[]=$r;
    }
    
    foreach ($array as $row) { 
      $part_info = array('part_no' => $row['PartNo'], 'unit_price' => $row['UnitPrice']);
      $temp=searchSub ($rs, $row['LineItemNo']);
    
        if ($temp===false){
           $rs[$counter] = array('LineItemNo' => $row['LineItemNo'], 'SolNo' => $row['SolNo'], 'St' => $row['St']);
           $rs[$counter]['parts'][] = $part_info;
           $counter++;
        }
        else {
            $rs[$temp]['parts'][]= $part_info;
        }
    }
    //function for subarray search
    function searchSub($arr, $keyword){
        foreach($arr as $key=>$value)
        {
            if (in_array($keyword, $value, true)!=false){
            return $key;
            }
        }
        return false;
    }
    $output['data']=$rs;
    print_r($output);
    

    Test Result

    【讨论】:

    • 为什么是计数器? $key 会做同样的事情。这是多余的。还有为什么要搜索功能?
    • @MikeBarwick OP 想要将共享相同 lineitemnosolnostparts_info 移动到作为数组 parts 的子数组,而不仅仅是移动 part_info到子数组。我希望我没有误解问题
    • @MikeBarwick $key 将产生 5 个子数组,在“数据”之后的级别,OP 想要的输出应该在“数据”之后的级别只有 2 个子数组
    • 没有。我很有可能放弃了。希望这可以解决 OP。 :)
    • 不,SML,您正确解释了这个问题。感谢您对此进行尝试。我发现当我运行这段代码时,第一个元素的所有值都是“1”(包括零件的所有值),第二个元素是“S”,第三个元素是“O”,第一个元素是“F”第四。不知道这是从哪里来的,但我在搞乱 foreach 时也有类似的情况。此外,第一部分有四个部分,接下来的三个部分有两个。应该有两个顶级元素(将数据删除到最后是个好主意),每个元素包含三个部分。
    【解决方案2】:

    array_push 是我通常会这样做的方式。你的代码读起来有点混乱(不是很用户友好),但我认为你很接近 - 非常接近......

    编辑:查看以下内容。应该管用。将您的 while 更改为 foreach 并像这样运行它:

    $rs = [];
    
    foreach(mysql_fetch_array($result) as $key => $row) 
    {
        $rs['data'][$key] = array('LineItemNo' => $row['LineItemNo'], 'SolNo' => $row['SolNo'], 'St' => $row['St']);
    
        $part_info = array('part_no' => $row['PartNo'], 'unit_price' => $row['UnitPrice']);
        $rs['data'][$key]['parts'] = $part_info;
    }
    
    print_r($rs);
    

    【讨论】:

    • 谢谢迈克。那更近了,但不是一路。我只得到第一个顶级元素的部分。我将编辑我的帖子以包含此内容。
    • 好吧,我猜不知道该怎么做。我也编辑了我的答案以显示我尝试过的内容。哦,我不得不使用array() 而不是[],由于某种原因我遇到了语法错误。这可能与问题有关吗?
    • 检查我的编辑以获取一些想法。注意,$rs[data][parts] 应该是 $rs['data']['parts']
    • 奇怪的是,我认为键也必须用引号引起来,但我没有尝试过,但它们起作用了。
    • Prob 解释了为什么 [] 不能作为 na 数组工作 - 因为它是同一回事。你用的是什么 PHP 版本?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-09
    • 1970-01-01
    • 2017-03-22
    • 1970-01-01
    • 1970-01-01
    • 2021-08-11
    • 2012-10-21
    相关资源
    最近更新 更多