3

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?

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

Keng
  • 52,011
  • 32
  • 81
  • 111
The Unknown
  • 19,224
  • 29
  • 77
  • 93

5 Answers5

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.

Brian Ramsay
  • 7,536
  • 8
  • 41
  • 52
1

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...

The Unknown
  • 19,224
  • 29
  • 77
  • 93
0

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

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

Matthew Groves
  • 25,181
  • 9
  • 71
  • 121
  • the problem with array_filter is that he needs to know whether or not there are any other entries with that value from within the comparator. I couldn't think of a way to do that that was any simpler or clearer than just iterating over it yourself. – Brian Ramsay Jul 16 '09 at 18:59
0

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

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;
}
Peter Bailey
  • 105,256
  • 31
  • 182
  • 206
0

You can indeed use array_filter for filtering your data:

$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.

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

usort($bb, function($a, $b) {
    return ($a['Spark Plugs'] > $b['Spark Plugs']
            ? 1
            : -1);
});
aurora
  • 9,607
  • 7
  • 36
  • 54