Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHP - How do you find duplicate value groupings in an array

I have an array of string values which sometimes form repeating value patterns ('a', 'b', 'c', 'd')

$array = array(
    'a', 'b', 'c', 'd',
    'a', 'b', 'c', 'd',
    'c', 'd',
);

I would like to find duplicate patterns based on the array order and group them by that same order (to maintain it).

$patterns = array(
    array('number' => 2, 'values' => array('a', 'b', 'c', 'd')),
    array('number' => 1, 'values' => array('c'))
    array('number' => 1, 'values' => array('d'))
);

Notice that [a,b], [b,c], & [c,d] are not patterns by themselves because they are inside the larger [a,b,c,d] pattern and the last [c,d] set only appears once so it's not a pattern either - just the individual values 'c' and 'd'

Another example:

$array = array(
    'x', 'x', 'y', 'x', 'b', 'x', 'b', 'a'
  //[.......] [.] [[......]  [......]] [.]
);

which produces

$patterns = array(
    array('number' => 2, 'values' => array('x')),
    array('number' => 1, 'values' => array('y')),
    array('number' => 2, 'values' => array('x', 'b')),
    array('number' => 1, 'values' => array('a'))
);

How can I do this?

like image 226
Xeoncross Avatar asked Jan 22 '14 22:01

Xeoncross


People also ask

How do you check if there are duplicate elements in an array?

function checkIfArrayIsUnique(myArray) { for (var i = 0; i < myArray. length; i++) { for (var j = 0; j < myArray. length; j++) { if (i != j) { if (myArray[i] == myArray[j]) { return true; // means there are duplicate values } } } } return false; // means there are no duplicate values. }

How do you find duplicate numbers in an array if it contains multiple duplicates PHP?

Definition and Usage. The array_unique() function removes duplicate values from an array. If two or more array values are the same, the first appearance will be kept and the other will be removed.

How do you count occurrences of each element in an array in PHP?

array_count_values() function in PHP The array_count_values() function returns an array with the number of occurrences for each value. It returns an associative array. The returned array has keys as the array's values, whereas values as the count of the passed values.


2 Answers

Character arrays are just strings. Regex is the king of string pattern matching. Add recursion and the solution is pretty elegant, even with the conversion back and forth from character arrays:

function findPattern($str){
    $results = array();
    if(is_array($str)){
        $str = implode($str);
    }
    if(strlen($str) == 0){ //reached the end
        return $results;
    }
    if(preg_match_all('/^(.+)\1+(.*?)$/',$str,$matches)){ //pattern found
        $results[] = array('number' => (strlen($str) - strlen($matches[2][0])) / strlen($matches[1][0]), 'values' => str_split($matches[1][0]));
        return array_merge($results,findPattern($matches[2][0]));
    }
    //no pattern found
    $results[] = array('number' => 1, 'values' => array(substr($str, 0, 1)));
    return array_merge($results,findPattern(substr($str, 1)));
}

You can test here : https://eval.in/507818 and https://eval.in/507815

like image 111
Nick Kuznia Avatar answered Oct 09 '22 21:10

Nick Kuznia


If c and d can be grouped, this is my code:

<?php
$array = array(
    'a', 'b', 'c', 'd',
    'a', 'b', 'c', 'd',
    'c', 'd',
);

$res = array();

foreach ($array AS $value) {
    if (!isset($res[$value])) {
        $res[$value] = 0;
    }
    $res[$value]++;
}

foreach ($res AS $key => $value) {
    $fArray[$value][] = $key;
    for ($i = $value - 1; $i > 0; $i--) {
        $fArray[$i][] = $key;
    }
}

$res = array();
foreach($fArray AS $key => $value) {
    if (!isset($res[serialize($value)])) {
        $res[serialize($value)] = 0;
    }
    $res[serialize($value)]++;
}
$fArray = array();
foreach($res AS $key => $value) {
    $fArray[] = array('number' => $value, 'values' => unserialize($key));
}

echo '<pre>';
var_dump($fArray);
echo '</pre>';

Final result is:

array (size=2)
  0 => 
    array (size=2)
      'number' => int 2
      'values' => 
        array (size=4)
          0 => string 'a' (length=1)
          1 => string 'b' (length=1)
          2 => string 'c' (length=1)
          3 => string 'd' (length=1)
  1 => 
    array (size=2)
      'number' => int 1
      'values' => 
        array (size=2)
          0 => string 'c' (length=1)
          1 => string 'd' (length=1)
like image 26
zeflex Avatar answered Oct 09 '22 21:10

zeflex