展平多维数组并删除重复的子数组值

问题描述 投票:0回答:4

我需要在 woocommerce 中的产品属性的数据结构中进行排序,对每个属性及其值进行分组。

我现在的阵列

array (size=5)
  0 => 
    array (size=1)
      'pa_color' => 
        array (size=1)
          0 => string 'red' (length=3)
  1 => 
    array (size=1)
      'pa_color' => 
        array (size=1)
          0 => string 'red' (length=3)
  2 => 
    array (size=2)
      'pa_color' => 
        array (size=1)
          0 => string 'gray' (length=4)
      'pa_modello' => 
        array (size=1)
          0 => string 'modello2' (length=8)
  3 => 
    array (size=1)
      'pa_color' => 
        array (size=1)
          0 => string 'yellow' (length=6)
  4 => 
    array (size=0)
      empty

我需要合并类似的内容:

array (size=1)
      'pa_color' => 
        array (size=1)
          0 => string 'red' (length=3)
          1 => string 'gray' (length=4)
          2 => string 'yellow' (length=6)
       
       'pa_modello' => 
            array (size=1)
              0 => string 'modello2' (length=8)

将相同键的值分组到一个数组中。

提前致谢

php wordpress multidimensional-array woocommerce array-merge
4个回答
0
投票
global $wp_query;
    $obj = get_queried_object();
    foreach ($wp_query->posts as $_post) {

        $_product = wc_get_product($_post->ID);
        $wc_attr_objs = $_product->get_attributes();
        $prod_attrs = [];

        foreach ($wc_attr_objs as $wc_attr => $wc_term_objs) {
            $prod_attrs[$wc_attr] = [];

            $wc_terms = $wc_term_objs->get_terms();


            foreach ($wc_terms as $wc_term) {
                 array_push($prod_attrs[$wc_attr], $wc_term->slug);


                var_dump($prod_attrs);


             }
        }

      $totals[] = $prod_attrs;

    } 

0
投票

$array
是你的数组:

foreach ($array as $item)
{
   if ($item['pa_color']['0']) $color[ $item['pa_color']['0'] ] = $item['pa_color']['0'];
   if ($item['pa_modello']['0']) $modello[$item['pa_modello']['0']] = $item['pa_modello']['0'];
// this loop will remove the duplicated values and I Assume each pa_color , pa_modello in the original array contains only one element with 0 as a key
}
foreach ($color as $c) $newArray['pa_color'][] = $c;
foreach ($modello as $m) $newArray['pa_modello'][] = $m;

这应该可以完成工作。

编辑:

对于动态属性注释:

foreach ($array as $item)
   foreach (array_keys($item) as $key) // getting the keys ex: pa_color 
   {
      if ($item[$key]['0']) {
         $temparray[$key][ $item[$key]['0'] ] = $item[$key]['0'];
      }
      // this loop will remove the duplicated values and I Assume each key in the original array contains only one element with 0 as a key
// the temparray will contain in its keys ($key) the pa_color , pa_module.. etc 
// each of them will be an array with the key=value approach .. in case having two "red" it will not duplicate 
   }
// finally making it zero based array 
foreach ($temparray as $key=>$item) // ex: $temparray['pa_color']['red'] = 'red'
   foreach ($item as $value) // ex: $item['red'] = 'red'
      $newArray[$key][] = $value; // ex: $newArray['pa_color'][0] = 'red';

看起来很复杂..我找不到更好的方法。


0
投票

循环第一级条目,然后添加一个嵌套循环以根据子数组中的所需键和值创建变量。

因为最深的子数组中只有一个元素,所以您可以在嵌套循环内使用“数组解构”将单个元素值分配为

$value

通过将

$value
声明为结果数组中深度值的键,确保输出中的值唯一。

如果您确实希望对子数组重新索引,则可以使用

array_map()
array_values()
来实现这一点 - 但仅在必要时才执行此操作。

代码:(演示

$result = [];
foreach ($array as $entries) {
    foreach ($entries as $key => [$value]) {
        $result[$key][$value] = $value;
    }
}

var_export($result);

输出:

array (
  'pa_color' => 
  array (
    'red' => 'red',
    'gray' => 'gray',
    'yellow' => 'yellow',
  ),
  'pa_modello' => 
  array (
    'modello2' => 'modello2',
  ),
)

附注如果您的深层子数组可能有多个元素,那么只需用另一个循环来适应它即可迭代该级别。

$result = [];
foreach ($array as $entries) {
    foreach ($entries as $key => $values) {
        foreach ($values as $value) {
            $result[$key][$value] = $value;
        }
    }
}

翻译成您在自我回答帖子中编写的代码,我认为它可能看起来像这样:

global $wp_query;
$prod_attrs = [];
foreach ($wp_query->posts as $_post) {
    foreach (wc_get_product($_post->ID)->get_attributes() as $wc_attr => $wc_term_objs) {
        foreach ($wc_term_objs->get_terms() as $wc_term) {
             $prod_attrs[$wc_attr][$wc_term->slug] = $wc_term->slug;
         }
    }
}
var_export($prod_attr);

0
投票

组合数组的最简单方法是在数组的数组上使用

array_merge_recursive
和 splat 运算符 (
...
)。

splat 运算符将解压缩可用于递归合并它们的数组。

$expected = array_merge_recursive(...$array);

此外,如果您只需要合并数组中的唯一值,您可以像这样使用

array_map

$unique = array_map('array_unique', $expected);

有关 splat 运算符的更多信息

评论后编辑

因为我自己一直大量使用这种方法,所以我做了一些测试,看看哪种方法更快。

分享结果:

问题:这两种方法哪个更快?

方法一:

array_map('array_unique', array_merge_recursive(...$array));

方法 2:使用
foreach
,如 mickmackusa 的回答中所述

使用大小为 5、50、100 和 500 的数组进行测试
将每个函数循环 10000 和 100000。

T1 是

array_merge_recursive
所用的时间,T2 是
foreach

所用的时间
数组大小 循环计数 T1 T2 更快 差异
5 10,000 0.041 0.0206 foreach 0.0204
5 100,000 0.2061 0.2082 数组合并递归 0.002
5 500,000 1.0315 1.0611 数组合并递归 0.0296
50 10,000 0.046 0.1878 数组合并递归 0.1418
50 100,000 0.4452 1.8877 数组合并递归 1.4425
100 10,000 0.0697 0.3729 数组合并递归 0.3032
100 100,000 0.6795 3.7464 数组合并递归 3.0669
500 10,000 0.2542 1.8674 数组合并递归 1.6132
500 100,000 2.5359 18.6922 数组合并递归 16.1562

结论:

  1. 对于小型阵列,使用什么并不重要。我在 500,000 次循环后才注意到差异
  2. 区别在于使用更大的数组时。当处理计数为 500 的数组时,
    foreach
    需要 16.1562 秒以上

因此,如果您有较小的数组,请使用您想要的任何内容。对于更大的数组,一定要避免

foreach
并使用
array_merge_recursive

链接到测试沙箱

© www.soinside.com 2019 - 2024. All rights reserved.