【问题标题】:Recursively search a sub-string in array with strings使用字符串递归搜索数组中的子字符串
【发布时间】:2015-09-28 02:35:50
【问题描述】:

对于下一个数组,每个子数组的键表示节点id(0)和类别名称(1)。
我要做的是找到每个子类别的父节点 ID。

例如,“3968976031”的父 ID 为“10176091”,“3968980031”的父 ID 为“3968977031”。
为了定义谁是父母,我们必须查看类别:
Küche & Haushalt/Heimtextilien, Bad- & Bettwaren/Babybettausstattung 的父级是 Küche & Haushalt/Heimtextilien, Bad- & Bettwaren

任何形式的帮助都将不胜感激。

数组(6){ [0]=> 数组(2){ [0]=> 字符串(8)“10176091” [1]=> string(48) "Küche & Haushalt/Heimtextilien, Bad- & Bettwaren" } [1]=> 数组(2){ [0]=> 字符串(10)“3968976031” [1]=> string(68) "Küche & Haushalt/Heimtextilien, Bad- & Bettwaren/Babybettausstattung" } [2]=> 数组(2){ [0]=> 字符串(10)“3968977031” [1]=> string(88) "Küche & Haushalt/Heimtextilien, Bad- & Bettwaren/Babybettausstattung/Babybettausstattung" } [3]=> 数组(2){ [0]=> 字符串(10)“3968978031” [1]=> string(99) "Küche & Haushalt/Heimtextilien, Bad- & Bettwaren/Babybettausstattung/Babybettausstattung/Bettbezüge" } [4]=> 数组(2){ [0]=> 字符串(10)“3968979031” [1]=> string(99) "Küche & Haushalt/Heimtextilien, Bad- & Bettwaren/Babybettausstattung/Babybettausstattung/Bettdecken" } [5]=> 数组(2){ [0]=> 字符串(10)“3968980031” [1]=> string(104) "Küche & Haushalt/Heimtextilien, Bad- & Bettwaren/Babybettausstattung/Babybettausstattung/Bettwäsche-Sets" } }

【问题讨论】:

  • 数组条目是否总是按此处所示的降序排列?
  • 是的,它会遵循这个模式

标签: php arrays string recursion


【解决方案1】:

使用 foreach :

$seenCategories = array();
foreach($myArray as $key => $subArray) {

    $id = $subArray[0];
    $category = $subArray[1]; 
    // $category = Küche & Haushalt/Heimtextilien, Bad- & Bettwaren/Babybettausstattung/Babybettausstattung/Bettwäsche-Sets

    // saving category in order to be found as a parent in the future
    $seenCategories[$category] = $id;

    // parsing category in order to find parent
    $categoriesList = explode('/', $category);
    $nbSubCategories = count($categoriesList);
    // we remove the last subcategory (Bettwäsche-Sets) to find the parent
    unset($categoriesList[$nbSubCategories-1]);
    $parentCategory = implode("/", $categoriesList);
    // $parentCategory = Küche & Haushalt/Heimtextilien, Bad- & Bettwaren/Babybettausstattung/Babybettausstattung

    // deleted loop due to performence leak
    /*$parentId = null;
    for($testingKey = $key-1; $testingKey >= 0; $testingKey--) {
        if($parentCategory == $myArray[$testingKey][1]) {
            // we found the parent
            $parentId = $myArray[$testingKey][0];
            // let's exit loop
            break;
        }
    }*/

    // performence improvement
    // if we've already seen the parent, we get its id (we suppose a parent can't be after a children)
    if(array_key_exists($parentCategory, $seenCategories) {
        $parentId = $seenCategories[$parentCategory];
    } else {
        $parentId = null;
    }

    echo "id of item : $id, category : $category, parentId : $parentId";
}

编辑:

根据 Mr.DOS 的评论改进了性能。谢谢。

【讨论】:

  • 非常抱歉,我误导了你。编辑不正确。 '3968980031' 的父 ID 是 '3968977031' 。您可以通过打破'/'来分析字符串来检查
  • @MihaiGabrielZamfir 我编辑了我的答案,所以我们正在寻找直接父母。如果缺少,则 id 将为空
  • 此解决方案涉及为数组中的每个元素循环整个数组一次。从算法分析的角度来看,它被称为 O(n^2) 解决方案。它可以工作,但效率不如预期。一个主要的改进是构建一个关联数组,其中子类别名称作为键,节点 ID 作为值,然后在确定父类别后,使用它在该地图上执行查找,而不是再次遍历整个数组。
  • @Mr.DOS 我改进了性能,感谢您的评论。
【解决方案2】:

如果子类总是跟随父类,并且数组只包含树的一个分支,我们可以很容易地根据数组中的前辈获取每个子类的父 ID。这种方法比@Random 的解决方案效率更高,因为它不需要为每个子数组对整个数组进行第二次遍历,并且不涉及字符串操作。

for ($i = 1; $i < count($categories); $i++)
{
    $id = $categories[$i][0];
    $name = $categories[$i][1];
    $parent_id = $categories[$i - 1][0];

    printf('ID: %s; category: %s; parent ID: %s',
           $id, $name, $parent_id);
}

【讨论】:

  • 问题是同一个parent可能有多个children,所以$i-1可能是兄弟……你得看类别(每个节点都包含/)跨度>
  • 在这种情况下,@Random 解决方案的变体几乎是您能做的最好的。我将对此发表另一条评论,表明可能有重大改进。
猜你喜欢
  • 1970-01-01
  • 2019-03-09
  • 2011-07-04
  • 2023-04-02
  • 2021-07-12
  • 2013-01-09
  • 2022-01-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多