【问题标题】:Manipulating multidimensional PHP array操作多维 PHP 数组
【发布时间】:2014-08-14 11:51:19
【问题描述】:

我正在使用多维 PHP 数组来跟踪对象,如下所示:

Array(
    ["name1"] => Array(
        ["data"] => Array(
           ["children"] => Array(
               ["name2"] => Array(
                   ["data"] => Array(
                       ["otherData"] => 2
                   )
               ),
               ["name3"] => Array(
                   ["data"] => Array()
               )
           )
        )
    ),
    ["name4"] => Array(
        ["data"] => Array(
            ["someRandomValue"] => "hi"
        )
    )
)

这可以是任意数量的级别,所以我会

需要一个递归函数来添加一个新对象。

我想做这样的事情:

function addToArray($item, $array) {
    if ($item-getData('insertBefore')) {
        //...
    }
    if ($item-getData('insertAfter')) {
        //...
    }
    if ($item-getData('parent')) {
        //...
    }
    foreach($array as &$arraySlice) {
        //..magic here
    }
}

基本上,该函数会尝试尊重 3 个数据选项 parentinsertBeforeinsertAfter 尽其所能。 如果与之前和之后的信息冲突,则会出错 并且缺少父(以及之前/之后)信息只需附加为 最后一个索引,在“name4”之后。

这样一个名为name5的新项目

parent 设置为name1

insertBefore 设置为 name3 插入如下:

Array(
    ["name1"] => Array(
        ["data"] => Array(
           ["children"] => Array(
               ["name2"] => Array(
                   ["data"] => Array(
                       ["otherData"] => 2
                   )
               ),
               ["name5"] => Array(
                   ["data"] => Array(
                       ["parent"] => "name1",
                       ["insertBefore"] => "name3"
                   )
               ),
               ["name3"] => Array(
                   ["data"] => Array()
               )
           )
        )
    ),
    ["name4"] => Array(
        ["data"] => Array(
            ["someRandomValue"] => "hi"
        )
    )
)

有什么建议吗?在我的尝试中,我似乎无法做到这一点。删除任何“nameX”条目的另一个功能也很棒。


编辑:这是我在困惑而放弃之前的最新尝试

function addToArray($item, $array) {
    $parent = isset($item->getData('parent'))   ? $item->getData('parent')   : null;
    $before = isset($item->getData('insertBefore')) ? $item->getData('insertBefore') : null;
    $after  = isset($item->getData('insertAfter'))  ? $item->getData('insertAfter')  : null;

    $parentFound = null;
    $prevPart    = null;

    // use & in the loop to work with a reference
    foreach($layout as $key => &$part) {
        if ($key == $parent) {
            $parentFound = 1;
        }

        if ($parentFound || !$parent) {
            if ($after) {
                //..
            }
            if ($before) {
                //..
            }
            //eh, erhm..
        } else if ($part['data']['children']) {
            if (addToArray($item, $part)) {
                return true;
            }
        }
        $prevPart = $part;
    }
    return false;
}

【问题讨论】:

  • 你有哪些不成功的尝试?
  • 好吧,一件事我什至不知道如何在递归地找到它应该在的位置后插入原始数组。记下我在哪里,并使用某种 array_splice 和array_merge 东西?或者,也许最好在我遍历原始数组时构建一个单独的副本,然后在构建副本后替换(或合并)原始数组?我基本上陷入了思考,现在我没有完整的功能可以展示,因为我在中途放弃了大多数尝试。
  • "name" 键至少在您的结构中是唯一的?
  • 是的,我还在帖子中添加了我最新的半成品尝试。
  • 闻起来像 XY 问题。也许告诉我们你真正想要做什么

标签: php arrays object multidimensional-array


【解决方案1】:

如果不建立一个庞大的代码库来测试,很难帮助你解决这样的问题,所以我给你一个强大的注释库开始。

function my_recc_func ($parent, $before, $after, $array, $my_data) {

  // Lets search the name in the keys of my current node (root or children)
  foreach ($array as $key => $value) {
    if ($key == $parent) {
      // Found it, so I'll do something here, and return true anyway
      $pos = 0;
      // Now looking for after or before names, and finding the correct pos at which I want to add my_data
      foreach ($value[$data][$children] as $name => $arr) {
        ++$pos;
        if ($name == $after) {
          break;
        }
        if ($name == $before) {
          --$pos;
          break;
        }
      }
      // Using the array_slice trick to insert my_data where I want inside of the array
      // It is now my new children with data inserted
      $new_children = array_slice ($value[$data][$children], 0, $pos, true) + $my_data + array_slice, $pos, count($value[$data][$children]), true);
      // $value[$data][$children] becomes $new_children
      // Code it as you want, if you need references or not or with a temporary array
      return true;
    } else {
      // That name isn't the correct one, so I'll see in the children of that node
      if (my_recc_func($parent, $before, $after, $value[$data][$children])) {
        return true;
      }
      // If I didn't find it in the children nodes, I'll keep going with the following nodes of the current parent
    }
  }
  // Didn't find anything in the children or in the current node, bye
  return false;

}

您可能需要应用一些更改才能使其正常工作(正如您所说的使用引用,或检查前后之间的不连贯性),但主要逻辑在这里。

希望它可以帮助您获得有效的东西。

编辑:好的,看看你上次的尝试,看起来你已经有了非常相似的东西。如果你告诉我你的代码有什么问题,我会帮助你让它工作

【讨论】:

  • 看起来不错,即使只是位置计数和数组切片部分也可以帮助我解决这个问题。我将在今天晚些时候进行测试,并就我的结果回复您。谢谢!
  • 嗨,经过几个小时的折腾参考文献和诸如此类的东西,我设法让它工作了 - 谢谢你的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-07-02
  • 1970-01-01
  • 2022-08-19
  • 1970-01-01
  • 2012-06-15
  • 1970-01-01
  • 2011-05-06
相关资源
最近更新 更多