从PHP中的关联数组中删除dupes / sort

时间:2022-08-26 14:07:47

I have a array of associative arrays

我有一组关联数组

aa[] = ('Tires'=>100, 'Oil'=>10, 'Spark Plugs'=>4 );
aa[] = ('Tires'=>454, 'Oil'=>43, 'Spark Plugs'=>3 );
aa[] = ('Tires'=>34,  'Oil'=>55, 'Spark Plugs'=>44 );
aa[] = ('Tires'=>454, 'Oil'=>43, 'Spark Plugs'=>45 );
aa[] = ('Tires'=>34,  'Oil'=>55, 'Spark Plugs'=>433 );
aa[] = ('Tires'=>23,  'Oil'=>33, 'Spark Plugs'=>44 );

Two Questions

  1. How can I remove duplicates according tot he field 'Oil' is there a array_unique which I can provide a callback which acts as a custom comparator?

    如何根据字段'Oil'删除重复项是否有一个array_unique,我可以提供一个回调作为自定义比较器?

  2. How can I sort by a custom field 'Spark Plugs'

    如何按自定义字段'Spark Plugs'排序

5 个解决方案

#1


  1. I don't know of a function you can use to do this. You will have to do a foreach over the values of the array and do the uniqueness checking manually.

    我不知道你可以用来做这个的功能。您将不得不对数组的值进行预测并手动执行唯一性检查。

  2. Use the usort() function and provide a custom comparator.

    使用usort()函数并提供自定义比较器。

#2


Instead of manually going and doing the usual duplicate checking, I did this

我做了这个,而不是手动去做通常的重复检查



$aa2 = array()

foeach($aa as $key => $value)  {
  $aa2[$value['Oil']] = $value;
}
$aa = $aa2;

Then sorting was done by the key...

然后按键完成排序......

#3


For question 1, I think array_filter is what you need.

对于问题1,我认为array_filter是你需要的。

And, like Brian says, usort for your second question.

而且,就像Brian说的那样,请回答你的第二个问题。

#4


The issue with remove dupes this way, is how do you determine which values remain, since you're talking about partial uniqueness.

以这种方式删除dupes的问题是,如何确定保留哪些值,因为您正在讨论部分唯一性。

This solution below just keeps the first to appear in index-order. It's not exactly elegant, but it works.

下面的解决方案只保留第一个以索引顺序出现的解决方案。它不是很优雅,但它有效。

<?php

$aa = array();
$aa[] = array('Tires'=>100, 'Oil'=>10, 'Spark Plugs'=>4 );
$aa[] = array('Tires'=>454, 'Oil'=>43, 'Spark Plugs'=>3 );
$aa[] = array('Tires'=>34,  'Oil'=>55, 'Spark Plugs'=>44 );
$aa[] = array('Tires'=>454, 'Oil'=>43, 'Spark Plugs'=>45 );
$aa[] = array('Tires'=>34,  'Oil'=>55, 'Spark Plugs'=>433 );
$aa[] = array('Tires'=>23,  'Oil'=>33, 'Spark Plugs'=>44 );

echo '<pre>';
print_r( arrayUniqeBySubKey( $aa, 'Oil' ) );
echo '</pre>';

function arrayUniqeBySubKey( $array, $key )
{
  $indexAggregates = array();

  foreach ( $array as $idx => $subArray )
  {
    $indexAggregates[$subArray[$key]][] = $idx;
  }

  foreach ( $indexAggregates as $originalIndexes )
  {
    $numOriginals = count( $originalIndexes );
    if ( 1 == $numOriginals )
    {
      continue;
    }
    for ( $i = 1; $i < $numOriginals; $i++ )
    {
      unset( $array[$originalIndexes[$i]] );
    }
  }
  return $array;
}

#5


You can indeed use array_filter for filtering your data:

您确实可以使用array_filter过滤数据:

$bb = array_filter($aa, function($item) {
    static $tmp = array();

    if ($filter = !in_array($item['Oil'], $tmp)) {
        $tmp[] = $item['Oil'];
    }

    return $filter;
});

This uses a static variable inside the function to "remember" the Oil already returned. This works, because $tmp is used only during the execution of array_filter. If you wrap this into a function and call it multiple times for example, $tmp will always be an empty array for the first call of the function provided to array_filter.

这在函数内部使用静态变量来“记住”已经返回的Oil。这是有效的,因为$ tmp仅在执行array_filter期间使用。如果你将它包装成一个函数并多次调用它,例如,$ tmp将始终是一个空数组,用于第一次调用提供给array_filter的函数。

The second task, the sorting, can be done using usort with a custom sorting function:

第二个任务,即排序,可以使用带有自定义排序功能的usort来完成:

usort($bb, function($a, $b) {
    return ($a['Spark Plugs'] > $b['Spark Plugs']
            ? 1
            : -1);
});

#1


  1. I don't know of a function you can use to do this. You will have to do a foreach over the values of the array and do the uniqueness checking manually.

    我不知道你可以用来做这个的功能。您将不得不对数组的值进行预测并手动执行唯一性检查。

  2. Use the usort() function and provide a custom comparator.

    使用usort()函数并提供自定义比较器。

#2


Instead of manually going and doing the usual duplicate checking, I did this

我做了这个,而不是手动去做通常的重复检查



$aa2 = array()

foeach($aa as $key => $value)  {
  $aa2[$value['Oil']] = $value;
}
$aa = $aa2;

Then sorting was done by the key...

然后按键完成排序......

#3


For question 1, I think array_filter is what you need.

对于问题1,我认为array_filter是你需要的。

And, like Brian says, usort for your second question.

而且,就像Brian说的那样,请回答你的第二个问题。

#4


The issue with remove dupes this way, is how do you determine which values remain, since you're talking about partial uniqueness.

以这种方式删除dupes的问题是,如何确定保留哪些值,因为您正在讨论部分唯一性。

This solution below just keeps the first to appear in index-order. It's not exactly elegant, but it works.

下面的解决方案只保留第一个以索引顺序出现的解决方案。它不是很优雅,但它有效。

<?php

$aa = array();
$aa[] = array('Tires'=>100, 'Oil'=>10, 'Spark Plugs'=>4 );
$aa[] = array('Tires'=>454, 'Oil'=>43, 'Spark Plugs'=>3 );
$aa[] = array('Tires'=>34,  'Oil'=>55, 'Spark Plugs'=>44 );
$aa[] = array('Tires'=>454, 'Oil'=>43, 'Spark Plugs'=>45 );
$aa[] = array('Tires'=>34,  'Oil'=>55, 'Spark Plugs'=>433 );
$aa[] = array('Tires'=>23,  'Oil'=>33, 'Spark Plugs'=>44 );

echo '<pre>';
print_r( arrayUniqeBySubKey( $aa, 'Oil' ) );
echo '</pre>';

function arrayUniqeBySubKey( $array, $key )
{
  $indexAggregates = array();

  foreach ( $array as $idx => $subArray )
  {
    $indexAggregates[$subArray[$key]][] = $idx;
  }

  foreach ( $indexAggregates as $originalIndexes )
  {
    $numOriginals = count( $originalIndexes );
    if ( 1 == $numOriginals )
    {
      continue;
    }
    for ( $i = 1; $i < $numOriginals; $i++ )
    {
      unset( $array[$originalIndexes[$i]] );
    }
  }
  return $array;
}

#5


You can indeed use array_filter for filtering your data:

您确实可以使用array_filter过滤数据:

$bb = array_filter($aa, function($item) {
    static $tmp = array();

    if ($filter = !in_array($item['Oil'], $tmp)) {
        $tmp[] = $item['Oil'];
    }

    return $filter;
});

This uses a static variable inside the function to "remember" the Oil already returned. This works, because $tmp is used only during the execution of array_filter. If you wrap this into a function and call it multiple times for example, $tmp will always be an empty array for the first call of the function provided to array_filter.

这在函数内部使用静态变量来“记住”已经返回的Oil。这是有效的,因为$ tmp仅在执行array_filter期间使用。如果你将它包装成一个函数并多次调用它,例如,$ tmp将始终是一个空数组,用于第一次调用提供给array_filter的函数。

The second task, the sorting, can be done using usort with a custom sorting function:

第二个任务,即排序,可以使用带有自定义排序功能的usort来完成:

usort($bb, function($a, $b) {
    return ($a['Spark Plugs'] > $b['Spark Plugs']
            ? 1
            : -1);
});