Question

I have the following data structure:

array (size=3)
  0 => 
    array (size=4)
      0 => string 'apple' (length=5)
      1 => string 'colophon' (length=8)
      2 => string 'byo-fusion-drive' (length=16)
      3 => string 'scroll-targeting' (length=16)
  1 => 
    array (size=3)
      0 => string 'apply' (length=5)
      1 => string 'exploring-web-typography' (length=24)
      2 => string 'on-performance-content-management' (length=33)
  2 => 
    array (size=3)
      0 => string 'macbook' (length=7)
      1 => string 'colophon' (length=8)
      2 => string 'nifty-minidrive' (length=15)

I'm trying to find out which, if any, arrays in my collection of arrays share a common value.

E.g: Arrays 0 and 2 share the string "colophon".

I've tried using array_intersect but this, of course, returns NULL since array 1 has no values in common with the others.

Also, it's possible (likely even) that in any given collection there will be no common value. The collection of arrays will always contain at least two arrays. There could be any number of additional arrays in the collection.

With the data described above, the end result should be something like this:

array (size=2)
  0 => 
    array (size=4)
      0 => string 'apple' (length=5)
      1 => string 'colophon' (length=8)
      2 => string 'byo-fusion-drive' (length=16)
      3 => string 'scroll-targeting' (length=16)
  1 => 
    array (size=3)
      0 => string 'macbook' (length=7)
      1 => string 'colophon' (length=8)
      2 => string 'nifty-minidrive' (length=15)

I.e: With array 1 (from the original) being removed as it shares no common value.

I'm sure there's a simple way to do this, but I have been trying for 8+ hours now and have decided to ask for help.

Anyone?

Was it helpful?

Solution

You'll need to iterate it with a nested loop. like so:

$array = array(
    array(
        "apple",
        "colophon",
        "byo-fusion-drive",
        "scroll-targeting"
    ),
    array(
        "apply",
        "exploring-web-typography",
        "on-performance-content-management"
    ),
    array(
        "macbook",
        "colophon",
        "nifty-minidrive"
    )
);

for ($i = 0; $i < count($array); $i++) {
    for ($j = $i+1; $j < count($array); $j++) {
        var_dump(array_intersect($array[$i], $array[$j]));
    }
}

Which outputs:

array (size=0)
  empty
array (size=1)
  1 => string 'colophon' (length=8)
array (size=0)
  empty

A simple modification to the loop gives the expected behavior:

$result = array();

for ($i = 0; $i < count($array); $i++) { //Start from the first array, and continue up to all of them.
    for ($j = $i+1; $j < count($array); $j++) { //Start with the current array of $i, +1. So that collisions never occur.
        if (count(array_intersect($array[$i], $array[$j])) !== 0) { //If there are common values (the array_intersect() function returns a non-empty array
            if (!in_array($array[$i], $result)) $result[] = $array[$i]; //Add the first array (if it's not there already)
            if (!in_array($array[$j], $result)) $result[] = $array[$j]; //Add the second array (if it's not there already)
        }
    }
}

Which outputs

array (size=2)
  0 => 
    array (size=4)
      0 => string 'apple' (length=5)
      1 => string 'colophon' (length=8)
      2 => string 'byo-fusion-drive' (length=16)
      3 => string 'scroll-targeting' (length=16)
  1 => 
    array (size=3)
      0 => string 'macbook' (length=7)
      1 => string 'colophon' (length=8)
      2 => string 'nifty-minidrive' (length=15)

OTHER TIPS

Try

$arr = array (
  array('apple', 'colophon', 'byo-fusion-drive', 'scroll-targeting', ),
  array('apply', 'exploring-web-typography', 'on-performance-content-management', ),
  array('macbook', 'colophon', 'nifty-minidrive', 'nifty-minidrive', ),
);

$repeated_values = array_keys(
  array_filter(
    array_count_values(
      array_reduce($arr, function ($res, $value) {
          return array_merge($res, array_unique($value));
        }, array()
      )
    ), function ($count) {
      return $count > 1;
  })
);

$result = array_filter($arr, function($value) use ($repeated_values) {
   if (sizeof(array_intersect($repeated_values, $value)) > 0) return true;
});

var_dump($result);

Output

array (size=2)
  0 => 
    array (size=4)
      0 => string 'apple' (length=5)
      1 => string 'colophon' (length=8)
      2 => string 'byo-fusion-drive' (length=16)
      3 => string 'scroll-targeting' (length=16)
  2 => 
    array (size=4)
      0 => string 'macbook' (length=7)
      1 => string 'colophon' (length=8)
      2 => string 'nifty-minidrive' (length=15)
      3 => string 'nifty-minidrive' (length=15)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top