oit oit oit oit - 22 days ago 9
PHP Question

Filtering an array of numbers according to a numeric pattern

There is an array of numbers:

$list = array
(
[0] => 111
[1] => 112
[2] => 113
[3] => 114
[4] => 121
[5] => 122
[6] => 123
[7] => 124
[8] => 131
[9] => 132
[10] => 1234
[11] => 1123
[12] => 1223
[13] => 1233
[14] => 4321
)


and a variable (the pattern):

$input = 1231;


I would like to filter the array with the following rules. Let
$list[$i]
be an item of the
$list
array,
$d
be a digit of
$list[$i]
. Then


  • if the count of digits equal to
    $d
    in
    $list[$i]
    is greater than the count of digits equal to
    $d
    in
    $input
    , then the array item must be skipped;

  • if there is no
    $d
    digit specified in
    $input
    , then the array item must be skipped.



For example, in the above-mentioned
$input
variable


  • 1
    appears twice,

  • 2
    and
    3
    appear once.



Then everything that appears more than this should be removed from the array:

$list = array
(
[0] => 111 ==> should be removed (1 is only defined twice in $input, so it shouldn't appear more than twice)
[1] => 112
[2] => 113
[3] => 114 ==> should be removed (there is no 4)
[4] => 121
[5] => 122 ==> should be removed (2 is only defined once, so it shouldn't appear more than once)
[6] => 123
[7] => 124 ==> should be removed (there is no 4)
[8] => 131
[9] => 132
[10] => 1234 ==> should be removed (there is no 4)
[11] => 1123
[12] => 1223 ==> should be removed (2 is only defined once in $input, so it shouldn't appear more than once)
[13] => 1233 ==> should be removed (3 is only defined once in $input, so it shouldn't appear more than once)
[14] => 4321 ==> should be removed (there is no 4)
)


How do I achieve this?

Answer
// Prepare counters for the digits in $input
foreach (str_split((string)$input) as $d)
  @$counters[$d]++;

$result = [];

foreach ($list as $key => $n) {
  // Counter for digits in $n
  $tmp_counter = [];

  foreach (str_split((string)$n) as $d) {
    // $d is not specified in $input, so skip $n
    if (empty($counters[$d]))
      continue 2;

    // The number of $d entries in $n is greater than
    // it is specified in $input, so skip $n
    if (@++$tmp_counter[$d] > $counters[$d])
      continue 2;
  }

  $result[$key] = $n;
}