Remove array positions that have the common name

Asked

Viewed 180 times

0

I want to take certain positions out of mine array which have the name of common positions, and play for another array.

EX:

array
  'id' => '147' 
  'nome' =>'João' 
  'email' => '[email protected]' 
  'data_nascimento' => '05/01/1987' 
  'numero_1' => '1' 
  'rua_1' => 'rua 1' 
  'numero_2' => '2' 
  'rua_2' => 'rua 2'
  'submit' => 'Salvar' 

Desired result in a array

array
  'numero_1' => '1' 
  'numero_2' => '2'

Or something like that

  • 3

    But what’s the common denominator? numero_1 and numero_2 are two different things. Or do you intend numero_X ?

  • 1

    What do you mean, "having the names of positions in common"? If you’re talking about the name of the key - what comes before the => - no two keys with the same name will exist in an array.

  • 1

    Why "rua_1" and "rua_2" did not follow the same criteria?

  • It did not follow the same pattern because I will take this array and do the foreach in both street and number, that is where there will be street number

4 answers

5

It seemed to me that the intention is to detect any duplicity in the name before underlining (underscore) and not only the "number". And example does not match the description of the question.

Then I came to this code:

$arr = array(
  'id'              => '147',
  'nome'            =>'João',
  'email'           => '[email protected]',
  'data_nascimento' => '05/01/1987',
  'numero_1'        => '1',
  'rua_1'           => 'rua 1', 
  'numero_2'        => '2',
  'rua_2'           => 'rua 2',
  'submit'          => 'Salvar' 
);
$newArr = array();
foreach ($arr as $k => $v) {
    $partes = explode("_", $k);
    if (count($partes) > 1) {
        $repetido = 0;
        foreach ($arr as $k2 => $v2) {
            if (strpos($k2, $partes[0]."_") === 0) {
                $repetido++;
            }
        }
        if ($repetido > 1)
            $newArr[$k] = $v;
    }
}
var_dump($newArr);

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

I think you can optimize something but the basis is this.

Upshot:

array(4) {
  ["numero_1"]=>
  string(1) "1"
  ["rua_1"]=>
  string(5) "rua 1"
  ["numero_2"]=>
  string(1) "2"
  ["rua_2"]=>
  string(5) "rua 2"
}

4


With your current code, for the stated purpose, you can do so:

$arr = array(
  'id'              => '147',
  'nome'            =>'João',
  'email'           => '[email protected]',
  'data_nascimento' => '05/01/1987',
  'numero_1'        => '1',
  'rua_1'           => 'rua 1', 
  'numero_2'        => '2',
  'rua_2'           => 'rua 2',
  'submit'          => 'Salvar' 
);

$newArr = array();

foreach ($arr as $k => $v)                    // por cada entrada na matriz
    if (strpos($k, "numero_") === 0)          // se começar por "numero_"
        $newArr[$k] = $v;                     // envia para a nova matriz

Whose result will be:

array(2) {
  ["numero_1"]=>
  string(1) "1"
  ["numero_2"]=>
  string(1) "2"
}

See example in Ideone.

3

If I understand correctly the goal is to transfer from the input array all elements that have the same prefix characterized by an expression followed by a underscore.

Therefore, I propose the scheme below:

$filtered = array();

array_walk(

    $arr,

    function( $current, $offset ) use( $arr, &$filtered ) {

         preg_match( '/(\w+_\d+)/', $offset, $matches );

        if( count( $matches ) > 0 && array_key_exists( $matches[ 1 ], $arr ) ) {

            $filtered[ $matches[ 1 ] ] = $current;
        }
    }
);

Using the input array with the same name as today ($arr) the resulting matrix $Filtered will have the following values:

array(
  'numero_1' => '1',
  'rua_1' => 'rua 1',
  'numero_2' => '2',
  'rua_2' => 'rua 2'
)

Your second question can be answered simply by computing the difference between the two original and filtered arrays:

$diff = array_diff_assoc( $arr, $filtered );

The matrix $diff has the following values:

array(
  'id' => '147',
  'nome' => 'João',
  'email' => '[email protected]',
  'data_nascimento' => '05/01/1987',
  'submit' => 'Salvar'
)

This approach has the advantages:

  • Do not depend on a fixed expression, that is, as long as all similarities follow the same format prefix, it will work in the whole matrix.
  • It is fast, because it needs calculations, complex conditions and nested loops. So even though large array is bad enough for your Application, this procedure won’t be your bottleneck.

2

My contribution, mixing a little of the answers already given:

$arr = array(
  'id'              => '147',
  'nome'            =>'João',
  'email'           => '[email protected]',
  'data_nascimento' => '05/01/1987',
  'numero_1'        => '1',
  'rua_1'           => 'rua 1', 
  'numero_2'        => '2',
  'rua_2'           => 'rua 2',
  'submit'          => 'Salvar' 
);

$padrao = "/[\w]+\_[\d]+/i";
$chaves = array_keys($arr);

foreach ($arr as $chaveAtual => $valor) {
    preg_match($padrao, $chaveAtual, $encontrados);
    $padraoEncontrado = count($encontrados);
    $padraoSeRepete = (int) preg_grep($padrao,$chaves);
    if ((!$padraoEncontrado) || (!$padraoSeRepete)) {
        unset($arr[$chaveAtual]);
    }
}

var_dump($arr);

/*
Resultado:
array(4) {  
  ["numero_1"]=>
  string(1) "1"
  ["rua_1"]=>
  string(5) "rua 1"
  ["numero_2"]=>
  string(1) "2"
  ["rua_2"]=>
  string(5) "rua 2"
}
*/

Browser other questions tagged

You are not signed in. Login or sign up in order to post.