Delimitadores php múltiplos em explodir


146

Estou com um problema, tenho uma matriz de cadeias e quero explodir em diferentes delimitadores. Por exemplo

$example = 'Appel @ Ratte';
$example2 = 'apple vs ratte'

e eu preciso de uma matriz que explode em @ ou vs.

Eu já escrevi uma solução, mas se todos tiverem uma solução melhor, poste aqui.

private function multiExplode($delimiters,$string) {
    $ary = explode($delimiters[0],$string);
    array_shift($delimiters);
    if($delimiters != NULL) {
        if(count($ary) <2)                      
            $ary = $this->multiExplode($delimiters, $string);
    }
    return  $ary;
}

Eu nunca vi uma pergunta com pessoas dando respostas como "Que tal isso", "Que tal isso"
HosseyNJF

Respostas:


290

que tal usar

$ output = preg_split ("/ (@ | vs) /", $ input);

Surpreendente. Pergunto-me como este giz contra explode()em argumentos individuais
Ascherer

6
Não importa, se você deseja criar um sistema grande com análise de string rígida, a maneira mais eficaz é o próprio analisador. Oterwise ele não tem muito efeito sobre a velocidade do sistema, mas você preffer de usar a maneira mais fácil para você (Para ser dinheiro efetivo)
sarjas

9
Observe que alguns caracteres precisam ser escapados para funcionar (como /, ?). Por exemplo: preg_split("/(\/|\?|=)/", $foo);.
Kenorb

preg_split retorna matriz indexada. É possível retornar associativo? Por exemplo $str='/x/1/2/3/4/5/y/100/200/z/777'; preg_split("/(x|y|z|)/", $str); e para verarray('x'=>'1/2/3/4/5', 'y'=>'100/200', 'z'=>'777')
LINKeRxUA

2
Descobri ter os espaços entre o / (e ) /impedido o preg_split de funcionar. Eu tinha que remover os espaços e, em seguida, ele funcionou como esperado (utilizando PHP 7)
Boardy

69

Você pode pegar a primeira corda, substituir todas @por vsusar str_replacee depois explodir vsou vice-versa.


1
Solução fácil, acabou usando-o para o código Json para substituir "}}" por "|". Sujo mas eficiente :)!
Baldráni 5/11

5
que gênio: D
Deadpool

isso não vai funcionar corretamente quando um delimitador é um super do outro (por exemplo, (@|@!)caso)

2
@vaxquis Sim, será. str_replace ('@!', '@', $ str); Certifique-se de começar com o delimitador mais exclusivo.
31518 John Ballinger

@JohnBallinger Não, não vai - você propôs outra solução, que mostra claramente o original solução não funcionará corretamente e que sua ideia é falha. Imagine que você não sabe qual é o superconjunto do outro. Você precisaria criar outra linha de código para verificar isso, etc. Embora eu odeie expressões regulares em geral, este é um caso em que é a melhor solução em termos de manutenção e simplicidade.

47
function multiexplode ($delimiters,$string) {

    $ready = str_replace($delimiters, $delimiters[0], $string);
    $launch = explode($delimiters[0], $ready);
    return  $launch;
}

$text = "here is a sample: this text, and this will be exploded. this also | this one too :)";


$exploded = multiexplode(array(",",".","|",":"),$text);

print_r($exploded);

//And output will be like this:
// Array
// (
//    [0] => here is a sample
//    [1] =>  this text
//    [2] =>  and this will be exploded
//    [3] =>  this also 
//    [4] =>  this one too 
//    [5] => )
// )

Fonte: php @ metehanarslan em php.net


14

Que tal usar strtr()para substituir todos os seus outros delimitadores pelo primeiro?

private function multiExplode($delimiters,$string) {
    return explode(
        $delimiters[0],
        strtr(
            $string,
            array_combine(
                array_slice(    $delimiters, 1  ),
                array_fill(
                    0,
                    count($delimiters)-1,
                    array_shift($delimiters)
                )
            )
        )
    );
}

É meio ilegível, eu acho, mas eu testei como trabalhando aqui.

One-liners ftw!


11

Não strtok()funcionaria para você?


1
vendo que o delimitador é 'vs', isso pode não funcionar como o php docu diz: strtok () divide uma string (str) em strings menores (tokens), com cada token sendo delimitado por qualquer caractere do token. e 'vs' contém dois caracteres
mikewasmike 17/12/2015

1
essa seria uma resposta melhor se você incluísse uma explicação ou exemplo. como é, é mais um comentário ...
billynoah

8

Simplesmente você pode usar o seguinte código:

$arr=explode('sep1',str_replace(array('sep2','sep3','sep4'),'sep1',$mystring));


2

Eu faço assim ...

public static function multiExplode($delims, $string, $special = '|||') {

    if (is_array($delims) == false) {
        $delims = array($delims);
    }

    if (empty($delims) == false) {
        foreach ($delims as $d) {
            $string = str_replace($d, $special, $string);
        }
    }

    return explode($special, $string);
}

Isso é o que eu estava procurando
Manojkiran.A

2

Que tal agora?

/**
 * Like explode with multiple delimiters. 
 * Default delimiters are: \ | / and ,
 *
 * @param string $string String that thould be converted to an array.
 * @param mixed $delimiters Every single char will be interpreted as an delimiter. If a delimiter with multiple chars is needed, use an Array.
 * @return array. If $string is empty OR not a string, return false
 */
public static function multiExplode($string, $delimiters = '\\|/,') 
{
  $delimiterArray = is_array($delimiters)?$delimiters:str_split($delimiters);
  $newRegex = implode('|', array_map (function($delimiter) {return preg_quote($delimiter, '/');}, $delimiterArray));
  return is_string($string) && !empty($string) ? array_map('trim', preg_split('/('.$newRegex.')/', $string, -1, PREG_SPLIT_NO_EMPTY)) : false;
}

No seu caso, você deve usar uma matriz para o parâmetro $ delimiters. Então é possível usar vários caracteres como um delimitador.

Se você não se importa com espaços à direita nos resultados, pode remover a array_map('trim', [...] )peça na linha de retorno. (Mas não se preocupe, neste caso. Mantenha o que está preg_splitnele.)

Versão necessária do PHP: 5.3.0 ou superior.

Você pode testá-lo aqui


1

Você terá alguns problemas (e se você tiver esta sequência: "vs @ maçãs" por exemplo) usando esse método de separação, mas se começarmos afirmando que você pensou sobre isso e corrigiu todas essas possíveis colisões, você poderia simplesmente substituir todas as ocorrências de $delimiter[1]to $delimiter[n]com $delimiter[0]e depois dividir a primeira?


1

Se o seu delimitador tiver apenas caracteres, você poderá usá-lo strtok, o que parece ser mais adequado aqui. Observe que você deve usá-lo com um whileloop para obter os efeitos.


0

Isso funcionará:

$stringToSplit = 'This is my String!' ."\n\r". 'Second Line';
$split = explode (
  ' ', implode (
    ' ', explode (
      "\n\r", $stringToSplit
    )
  )
);

Como você pode ver, primeiro cola as partes explodidas junto com um espaço, para depois separá-las novamente, desta vez ocupando os espaços com ele.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.