Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 基于部分数组键组合数组项_Php_Arrays - Fatal编程技术网

Php 基于部分数组键组合数组项

Php 基于部分数组键组合数组项,php,arrays,Php,Arrays,我有一个给定的多维数组,如: $givenArray = [ 'one__111__' => [ 'more' => '000'], 'one__111__xyz' => [ 'more' => '000'], 'hey__121__' => [ 'more' => '000'], 'hey__121__abc' => [ 'more' => '000'], 'zzz__212__' => [ 'mor

我有一个给定的多维数组,如:

$givenArray = [
    'one__111__' => [ 'more' => '000'],
    'one__111__xyz' => [ 'more' => '000'],
    'hey__121__' => [ 'more' => '000'],
    'hey__121__abc' => [ 'more' => '000'],
    'zzz__212__' => [ 'more' => '000'],
    'zzz__212__b' => [ 'more' => '000'],
    'abc__3__' => [ 'more' => '000'],
];
如果它们以相同的密钥名开始,我需要映射这些对。因此,
one_uu111_u
one_u111_uxyz
是一对

结果应该如下所示:

[
    ['one__111__'] => [
        [0] => ['one__111__' => ['more' => '000']],
        [1] => ['one__111__xyz' => ['more' => '000']]
    ],
    ['hey__121__'] =>
        [0] => ['hey__121__' => ['more' => '000']],
        [1] => ['hey__121__abc' => ['more' => '000']]
    ]
    ['zzz__212__'] =>
        [0] => ['zzz__212__' => ['more' => '000']],
        [1] => ['zzz__212__b' => ['more' => '000']]
    ]
    ['abc__3__'] =>
        [0] => ['abc__3__' => ['more' => '000']]
    ]
]
这就是我尝试过的。我相信是O(n2)

我搜索了数组filter/reduce/map函数,但找不到“正确”的函数。应该使用哪个数组函数?就像我想我需要一个数组函数,它迭代每个项目,并允许我传入新创建的数组。PHP中有这样的函数吗

这应该可以-

$new = [];
$keys = [];
// Extract keys as per pattern
foreach ($givenArray as $key => $val) {
    preg_match('/[a-z]+\_+\d+\_+/', $key, $match);
    $keys[] = $match[0];
}
// filter array for each extracted keys
foreach ($keys as $key) {
    $new[$key] = array_filter($givenArray, function($k) use($key) {
        return strpos($k, $key) !== false;
    }, ARRAY_FILTER_USE_KEY);
}
输出

Array
(
    [one__111__] => Array
        (
            [one__111__] => Array
                (
                    [more] => 000
                )

            [one__111__xyz] => Array
                (
                    [more] => 000
                )

        )

    [hey__121__] => Array
        (
            [hey__121__] => Array
                (
                    [more] => 000
                )

            [hey__121__abc] => Array
                (
                    [more] => 000
                )

        )

    [zzz__212__] => Array
        (
            [zzz__212__] => Array
                (
                    [more] => 000
                )

            [zzz__212__b] => Array
                (
                    [more] => 000
                )

        )

    [abc__3__] => Array
        (
            [abc__3__] => Array
                (
                    [more] => 000
                )

        )

)
这应该是有效的-

$new = [];
$keys = [];
// Extract keys as per pattern
foreach ($givenArray as $key => $val) {
    preg_match('/[a-z]+\_+\d+\_+/', $key, $match);
    $keys[] = $match[0];
}
// filter array for each extracted keys
foreach ($keys as $key) {
    $new[$key] = array_filter($givenArray, function($k) use($key) {
        return strpos($k, $key) !== false;
    }, ARRAY_FILTER_USE_KEY);
}
输出

Array
(
    [one__111__] => Array
        (
            [one__111__] => Array
                (
                    [more] => 000
                )

            [one__111__xyz] => Array
                (
                    [more] => 000
                )

        )

    [hey__121__] => Array
        (
            [hey__121__] => Array
                (
                    [more] => 000
                )

            [hey__121__abc] => Array
                (
                    [more] => 000
                )

        )

    [zzz__212__] => Array
        (
            [zzz__212__] => Array
                (
                    [more] => 000
                )

            [zzz__212__b] => Array
                (
                    [more] => 000
                )

        )

    [abc__3__] => Array
        (
            [abc__3__] => Array
                (
                    [more] => 000
                )

        )

)

只要键按示例数据中所示进行排序,您只需将当前键与插入到输出数组中的最后一个键进行比较:

$result = [];
$resultItemKey = '#';  // something that a key can't start with
foreach($givenArray as $key => $value) {
    if(substr($key, 0, strlen($resultItemKey)) === $resultItemKey)  {
        $result[$resultItemKey][] = [$key => $value];
    }
    else {
        $result[$key][] = [$key => $value];
        $resultItemKey = $key;
    }
}
输出太长,无法在此显示,但符合要求


请注意,如果未对键进行排序,则始终可以使用按键对数组进行排序。

只要按示例数据中所示对键进行排序,您只需将当前键与插入到输出数组中的最后一个键进行比较:

$result = [];
$resultItemKey = '#';  // something that a key can't start with
foreach($givenArray as $key => $value) {
    if(substr($key, 0, strlen($resultItemKey)) === $resultItemKey)  {
        $result[$resultItemKey][] = [$key => $value];
    }
    else {
        $result[$key][] = [$key => $value];
        $resultItemKey = $key;
    }
}
输出太长,无法在此显示,但符合要求


请注意,如果未对键进行排序,则始终可以使用按键对数组进行排序。

您可以先按键排序,然后“查看”下一个键,直到您停止查找与当前键以相同字符串开头的键为止

这会把你降到O(n)㏒ n) :

ksort($givenArray);//如果要保留原始阵列,请先克隆它
$result=[];
对于($i=0;$i[$givenArray[$thisKey]]];
而($i
您可以先按键排序,然后“窥视”下一个键,直到您停止查找与当前键以相同字符串开头的键为止,从而提高性能

这会把你降到O(n)㏒ n) :

ksort($givenArray);//如果要保留原始阵列,请先克隆它
$result=[];
对于($i=0;$i[$givenArray[$thisKey]]];
而($i
由于要查找前缀匹配和添加操作,因此可以构建数据结构。每个节点将携带它自己的子节点,以及当许多键具有相同前缀时,它最终将保存的数据

<?php

class Node{
    public $char,$data,$children,$end,$key;
    function __construct($char){
        $this->char = $char;
        $this->data = [];
        $this->children = [];
        $this->end = false;
    }
}

class Trie{
    private $root,$result;
    function __construct($data){
        $this->root = new Node('~');
        $this->result = [];
        foreach($data as $key => $value){
            $this->insert($key);
        }
        foreach($data as $key => $value){
            $this->add($key,$value);
        }
    }

    private function insert($key){
        $temp = $this->root;
        $len = strlen($key);
        for($i=0;$i<$len;++$i){
            if(!isset($temp->children[$key[$i]])){
                $temp->children[$key[$i]] = new Node($key[$i]);
            }
            $temp = $temp->children[$key[$i]];
            if($temp->end) break;
        }
        if(!$temp->end) $temp->key = $key;
        $temp->end = true;
    }

    private function add($key,$value){
        $temp = $this->root;
        $len = strlen($key);
        for($i=0;$i<$len;++$i){
            $temp = $temp->children[$key[$i]];
            if($temp->end) break;
        }
        $temp->data[] = [$key => [$value]];
    }

    public function getResult(){
        $this->getResultHelper($this->root);
        return $this->result;
    }

    private function getResultHelper(Node $root){
        if($root->end){
            $this->result[$root->key] = $root->data;
            return;
        }

        foreach($root->children as $key => $node){
            $this->getResultHelper($node);
        }
    }
}

print_r((new Trie($givenArray))->getResult());

由于您正在查找前缀匹配和添加操作,因此可以构建数据结构。每个节点将携带它自己的子节点,以及当许多键具有相同前缀时,它最终将保存的数据

<?php

class Node{
    public $char,$data,$children,$end,$key;
    function __construct($char){
        $this->char = $char;
        $this->data = [];
        $this->children = [];
        $this->end = false;
    }
}

class Trie{
    private $root,$result;
    function __construct($data){
        $this->root = new Node('~');
        $this->result = [];
        foreach($data as $key => $value){
            $this->insert($key);
        }
        foreach($data as $key => $value){
            $this->add($key,$value);
        }
    }

    private function insert($key){
        $temp = $this->root;
        $len = strlen($key);
        for($i=0;$i<$len;++$i){
            if(!isset($temp->children[$key[$i]])){
                $temp->children[$key[$i]] = new Node($key[$i]);
            }
            $temp = $temp->children[$key[$i]];
            if($temp->end) break;
        }
        if(!$temp->end) $temp->key = $key;
        $temp->end = true;
    }

    private function add($key,$value){
        $temp = $this->root;
        $len = strlen($key);
        for($i=0;$i<$len;++$i){
            $temp = $temp->children[$key[$i]];
            if($temp->end) break;
        }
        $temp->data[] = [$key => [$value]];
    }

    public function getResult(){
        $this->getResultHelper($this->root);
        return $this->result;
    }

    private function getResultHelper(Node $root){
        if($root->end){
            $this->result[$root->key] = $root->data;
            return;
        }

        foreach($root->children as $key => $node){
            $this->getResultHelper($node);
        }
    }
}

print_r((new Trie($givenArray))->getResult());


我认为密钥名称没有固定的长度/结构?@Nick没错,密钥是否总是按照示例数据中所示进行排序?@Nick luckley是的,但未来可能会发生变化future@caramba如果子前缀有自己的子前缀怎么办?我认为密钥名称没有固定的长度/结构?@Nick是的,密钥总是按照示例数据中所示进行排序吗?@Nick Luckley是的,但未来可能会发生变化future@caramba如果子前缀有自己的子前缀呢?我喜欢先生成keys数组的想法。正如我的问题所写的,钥匙确实有一个模式。在现实生活中,虽然这些键没有遵循这样的模式,但这仍然是O(n2),就像您的原始代码一样。如果模式不同并且有大量数据,那么应该避免这种情况,就像首先生成键数组的想法一样。正如我的问题所写的,钥匙确实有一个模式。在现实生活中,虽然这些键没有遵循这样的模式..但这仍然是O(n2),就像您的原始代码一样。如果模式不同并且有大量数据,那么应该避免这样:facepalm,这么简单
$resultItemKey
甚至可以设置为空字符串
$resultItemKey=''
..@caramba不,不能将其设置为空字符串,因为
substr($key,0,strlen($resultItemKey))
将返回
'
,而不管
$key
的值是多少,该值都将匹配
'
,但只有在密钥为空时才会发生这种情况,对吗?我总是希望有一把钥匙。。我猜
#
作为初始值可能更可靠。如果一个键是空的,那么之后的所有内容都会匹配它,因为空字符串是其他字符串的子字符串。对于您的数据来说,这似乎不是一个有效的场景。另一方面,它可能是
null
,并且可以添加额外的null检查来检查它是否是第一次。可能比试图找到一个不是任何键前缀的字符串更容易:facepalm,这么容易
$resultItemKey
甚至可以设置为空字符串
$resultItemKey=''
..@caramba不,不能将其设置为空字符串,因为
substr($key,0,strlen($resultItemKey))
将返回
'
,而不管
$key
的值是多少,该值都将匹配
'
,但只有在密钥为空时才会发生这种情况,对吗?我总是希望有一把钥匙。。我猜
#
作为初始值可能更可靠。如果一个键是空的,那么之后的所有内容都会匹配它,因为空字符串是其他字符串的子字符串。对于您的数据来说,这似乎不是一个有效的方案。另一方面,它可能是
null
,并且可以添加额外的null检查