PHP - 从数组中获取组合

PHP - Get combinations from array

我需要一个建议,如何从以下来源创建树视图。

$dataSrc = array(
 '1@02@43@170@1',
 '1@02@43@176@1',
 '1@02@43@182@1',
 '1@02@42@182@1',
 '1@02@42@176@1',
);

此字符串是产品的分组变体。每个参数由@分隔。所以如果我分解这个字符串,我会得到这些。

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 02
            [2] => 43
            [3] => 170
            [4] => 1
        )

    [1] => Array
        (
            [0] => 1
            [1] => 02
            [2] => 43
            [3] => 176
            [4] => 1
        )

    [2] => Array
        (
            [0] => 1
            [1] => 02
            [2] => 43
            [3] => 182
            [4] => 1
        )

    [3] => Array
        (
            [0] => 1
            [1] => 02
            [2] => 42
            [3] => 182
            [4] => 1
        )

    [4] => Array
        (
            [0] => 1
            [1] => 02
            [2] => 42
            [3] => 176
            [4] => 1
        )

)

现在我需要获取参数的组合,这是不一样的。结果应该是:

$resp = array(
  43 => array(
     170,
     176,
     182,
    ),
  42 => array(
     182,
     176,
   )
);

所以取消设置键,它们是相同的并且从组合中得到树。你能帮我吗?

其他详细信息(从 OP 的评论中编辑成问题——其中一些已被删除):

These strings (1@02@43@170@1) are combined variants of products (returned from external DB) 1 - some param 02 - color 43 - sizeA 178 - sizeB Each product is available in specific combinations, which are declared by these strings. So if I will have 1@02@43@170@1 and 1@02@43@176@1 it means that i have product with size 43 and in size 43 I have another variants 176 and 170. It's really hard to explain, but i need these values grouped.

I do not know which values are different. First of all, I need to know what parameters need to be grouped (it can be for example two or three params).

if values are same, it should not be grouped. If there will be 3 different values, it should be like that: $final = array( '02' => array( 42 => array( 170, 176, ), 43 => array( 182, 176, ), ), '03' => array( 42 => array( 170, 176, ), ) );

It should be grouped hierarchical, so first different value at parent level.

另一个可能的样本集:

$dataSrc2 = array(
    '1@02@43@170@1',
    '1@02@43@176@1',
    '1@02@43@182@1',
    '1@02@42@182@1',
    '1@02@42@176@1',
    '1@03@43@170@1',
    '1@03@43@176@1',
    '1@03@43@182@1',
    '1@03@42@182@1',
    '1@03@42@176@1',
);

Firstly check your exploded data is not empty

Have an array that will display the output, in our case say $ans

keep the first index of the array as first element of your exploded data

As you have your pivot in index 2 and value in index 3, we initialize our answer array as explodedarray's[0][2] < 2 because of your pivot

Now in your loop check if the index is already created, if not then create it. in our case we have already 42 as created so when it gets into the loop it wont create 42 for the first time, but when it sees 43 our isset() function will return false and our code will create a new index for our $ans array

Once this index creation is done you simply need to add in your [3] (as in our case this index is your value ) index to the current $ans array

<?php
        $dataSrc = array(
         '1@02@43@170@1',
         '1@02@43@176@1',
         '1@02@43@182@1',
         '1@02@42@182@1',
         '1@02@42@176@1',
        );
        
        $arr = array();
        foreach($dataSrc as $d)
        {
            
        $x[] = explode('@',$d); 
        }
        
        if(!empty($x))
        {
            $ans = array();
            $ans[$x[0][2]] = array();
            foreach($x as $dp)
            {
                if(!isset($ans[$dp[2]]))
                {
                    $ans[$dp[2]] = array();
                }
                $ans[$dp[2]][] = $dp[3];
            }
            
        }
        
        dd($ans)

@ 分隔的字符串数组解析为已知深度的嵌套结构后,您正在寻找一个未知深度的精简输出数组,其中顶层有多个条目。

为了实现这一点,我下面的代码会将字符串解析为 limited-depth 数组结构,然后如果只有一个条目则递归地去除顶层。结果数组要么是空数组(如果所有字符串都相同),要么具有包含多个条目的顶层。

代码:(Demo with 3 sample sets)

function killYourParentIfYouHaveOne($level) {
    if (count($level) === 1) {
         $key = key($level);
         $level = is_array($level[$key]) ? killYourParentIfYouHaveOne($level[$key]) : [];
    }
    return $level;
}

function differingTree(array $array): array {
    $result = [];
    foreach ($array as $item) {
        [$a, $b, $c, $d, $e] = explode('@', $item, 5);
        $result[$a][$b][$c][$d] = $e;
    }
    return killYourParentIfYouHaveOne($result);
}

foreach ($tests as $test) {
    echo var_export(differingTree($test), true) . "\n---\n";
}

示例输入:

$tests = [
    [
        '1@02@43@170@1',
        '1@02@43@176@1',
        '1@02@43@182@1',
        '1@02@42@182@1',
        '1@02@42@176@1',
    ],
    [
        '1@02@43@170@1',
        '1@02@43@176@1',
        '1@02@43@182@1',
        '1@02@42@182@1',
        '1@02@42@176@1',
        '1@03@43@170@1',
        '1@03@43@176@1',
        '1@03@43@182@1',
        '1@03@42@182@1',
        '1@03@42@176@1',
    ],
    [
        '1@02@43@170@1',
        '1@02@43@170@1',
    ]
];

生成的输出:

array (
  43 => 
  array (
    170 => '1',
    176 => '1',
    182 => '1',
  ),
  42 => 
  array (
    182 => '1',
    176 => '1',
  ),
)
---
array (
  '02' => 
  array (
    43 => 
    array (
      170 => '1',
      176 => '1',
      182 => '1',
    ),
    42 => 
    array (
      182 => '1',
      176 => '1',
    ),
  ),
  '03' => 
  array (
    43 => 
    array (
      170 => '1',
      176 => '1',
      182 => '1',
    ),
    42 => 
    array (
      182 => '1',
      176 => '1',
    ),
  ),
)
---
array (
)
---

据我所知,从你的问题来看,它只需要每个数据集中结构的第二、第三和第四个元素,我试图通过访问该数据集元素的索引来给出解决方案。

$dataSrc = [
   [
   '1@02@43@170@1',
   '1@02@43@176@1',
   '1@02@43@182@1',
   '1@02@42@182@1',
   '1@02@42@176@1',
   '1@03@43@170@1',
   '1@03@43@176@1',
   '1@03@43@182@1',
   '1@03@42@182@1',
   '1@03@42@176@1',
   ],
   [ 
   '1@02@43@170@1',
   '1@02@43@176@1',
   '1@02@43@182@1',
   '1@02@42@182@1',
   '1@02@42@176@1',
   ]


];

$result = [];
 
foreach ($dataSrc as $input_data ) {
   $result [] = process_input( $input_data );
}

var_dump( $result );


function process_input( $input_data )
{
   $data = [];
   array_walk( $input_data, function ( $each_row ) use ( &$data )
   {
      $data[] =  explode('@', $each_row);
   });
  
   $processed = [];
   
   foreach ($data as $value) {
      $processed [ $value[1] ] [ $value[2] ][] = (int) $value[3];
   }

   return (\count($processed ) === 1) ? array_pop( $processed ) : $processed;
   
}