tags:

views:

46

answers:

3

I have two arrays of the same length ($search_type, $search_term). I want to remove any duplicates in the sense of there being searches that have the same type and search term (ie $search_type[$a] == $search_type[$b] && $search_term[$a] == $search_term[$b]).

I'm aware that I could write this using loops, was wondering if there's a simpler (but equally efficient) way that takes advantage of built in functions?

A: 

Try either array_intersect() which will take two arrays and return an array where a value in array A exists in array B. Or array_diff() which does the opposite and returns an array of all values in A that don't exist in B.

Jonathan Kuhn
A: 

Ok, here's an overly complex ad-hoc function foo() (lacking error handling, documentation and testing) that combines those two arrays. array_unique() takes care of the duplicates.

<?php
$search_term = array('termA', 'termB', 'foo'=>'termC', 'bar'=>'termD', 'termB', 'termA');
$search_type= array('typeA', 'typeB', 'foo'=>'typeC', 'bar'=>'typeD', 'typeB', 'typeA');

$x = foo(array('term', $search_term), array('type', $search_type));
$x = array_unique($x, SORT_REGULAR);
var_dump($x);

function foo() {
  $rv = array();
  $params = func_get_args();
  foreach ( array_keys($params[0][1]) as $key ) {
    $rv[$key] = array();  
    foreach( $params as $p ) {
      $rv[$key][$p[0]] = $p[1][$key];  
    }
  }
  return $rv;
}

prints

array(4) {
  [0]=>
  array(2) {
    ["term"]=>
    string(5) "termA"
    ["type"]=>
    string(5) "typeA"
  }
  [1]=>
  array(2) {
    ["term"]=>
    string(5) "termB"
    ["type"]=>
    string(5) "typeB"
  }
  ["foo"]=>
  array(2) {
    ["term"]=>
    string(5) "termC"
    ["type"]=>
    string(5) "typeC"
  }
  ["bar"]=>
  array(2) {
    ["term"]=>
    string(5) "termD"
    ["type"]=>
    string(5) "typeD"
  }
}
VolkerK
Anyone know if foo() can be done in a shorter way using built in functions?
babonk
There is the MultipleIterator and iterator_to_array(). But unfortunately MultipleIterator::key() returns an array which causes an "invalid key" error with foreach/iterator_to_array :-/ Otherwise the function would be a bit shorter (and it would rely on the order of elements as the iterator returns them instead of using the keys). Are you sure changing the parameter names isn't an option? All you'd have to do is to name them like `name="foo[0][term]" ... name="foo[0][type]" ...foo[1][term]...foo[1][type]`.
VolkerK
A: 

It doesn't look like there's a simple way to solve the problem using just built-in functions.

This (at least logically) should work.

$search_terms = array('a', 'b', 'c', 'c', 'd', 'd');
$search_types = array( 1,   2,   3,   4,   5,   5);

$terms = array_fill_keys($search_terms, array());
// Loop through them once and make an array of types for each term
foreach ($search_terms as $i => $term)
    $terms[$term][] = $search_types[$i];

// Now we have $terms = array('a' => array(1),
//                            'b' => array(2),
//                            'c' => array(3, 4),
//                            'd' => array(5, 5)
//                      );

// Now run through the array again and get rid of duplicates.
foreach ($terms as $i => $types)
    $terms[$i] = array_unique($types);

Edit: Here's a shorter and presumably more efficient one where you end up with a less pretty array:

$search_terms = array('a', 'b', 'c', 'c', 'd', 'd');
$search_types = array( 1,   2,   3,   4,   5,   5);

$terms = array_fill_keys($search_terms, array());
// Loop through them once and make an array of types for each term
foreach ($search_terms as $i => $term)
    $terms[$term][$search_types[$i]] = 1;

// Now we have $terms = array('a' => array(1 => 1),
//                            'b' => array(2 => 1),
//                            'c' => array(3 => 1, 4 => 1),
//                            'd' => array(5 => 1)
//                      );
Casey Hope