Rozbij kilka ograniczników PHP


146

Mam problem, mam tablicę ciągów i chcę eksplodować w innym ograniczniku. Na przykład

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

i potrzebuję tablicy, która eksploduje w @ lub vs.

Napisałem już rozwiązanie, ale jeśli każdy ma lepsze rozwiązanie, napisz tutaj.

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;
}

Nigdy nie widziałem pytania, na które ludzie odpowiadaliby „Co powiesz na to”, „A co z tamtym”
HosseyNJF

Odpowiedzi:


290

co z używaniem

$ wyjście = preg_split ("/ (@ | vs) /", $ wejście);

Niesamowity. Zastanawiam się, jak to explode()
wypada

6
Nie ma znaczenia, jeśli chcesz stworzyć duży system z twardym parsowaniem ciągów znaków, najbardziej efektywnym sposobem jest własny parser. Oterwise nie ma to większego wpływu na szybkość systemu, ale wolisz używać najłatwiejszego sposobu dla siebie (Aby być efektywnym finansowo)
SergeS

9
Zwróć uwagę, że niektóre znaki muszą zostać zmienione, aby działały (takie jak /, ?). Na przykład: preg_split("/(\/|\?|=)/", $foo);.
kenorb

preg_split zwraca tablicę indeksowaną. Czy można zwrócić asocjacyjną? Na przykład $str='/x/1/2/3/4/5/y/100/200/z/777'; preg_split("/(x|y|z|)/", $str); i do zobaczeniaarray('x'=>'1/2/3/4/5', 'y'=>'100/200', 'z'=>'777')
LINKeRxUA

2
Znalazłem spacje między / (i ) /zatrzymałem działanie preg_split. Musiałem usunąć spacje, a potem działało zgodnie z oczekiwaniami (używając PHP 7)
Boardy

69

Można wziąć pierwszy ciąg, należy wymienić wszystkie @z vsużyciem str_replace, a następnie eksplodować na vsodwrót.


1
Proste rozwiązanie, skończyło się na użyciu go w kodzie Json, aby zastąpić „}}” przez „|”. Brudne, ale wydajne :)!
Baldráni

5
co za geniusz: D
Deadpool

to nie będzie działać poprawnie, gdy jeden separator jest nadzbiorem drugiego (np. (@|@!)przypadek)

2
@vaxquis Tak, będzie. str_replace ('@!', '@', $ str); Upewnij się, że zaczynasz od najbardziej unikalnego separatora.
John Ballinger,

@JohnBallinger Nie, nie będzie - zaproponowałeś inne rozwiązanie, z którego jasno wynika, że oryginalne rozwiązanie nie działa poprawnie, a Twój pomysł jest wadliwy. Wyobraź sobie, że nie wiesz, który z nich jest nadzbiorem drugiego. Będziesz musiał utworzyć kolejną linię kodu, aby to sprawdzić itp. Chociaż ogólnie nienawidzę wyrażeń regularnych, jest to przypadek, gdy jest to najlepsze rozwiązanie pod względem łatwości utrzymania i prostoty.

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] => )
// )

Źródło: php @ metehanarslan na php.net


14

A co powiesz strtr()na zastąpienie wszystkich pozostałych separatorów pierwszym?

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)
                )
            )
        )
    );
}

Wydaje mi się, że to trochę nieczytelne, ale przetestowałem to jako pracujące tutaj.

One-liners ftw!


11

Nie strtok()zadziała dla Ciebie?


1
widząc, że jego separatorem jest „vs”, może to nie działać, jak mówi php docu: strtok () dzieli ciąg (str) na mniejsze ciągi (tokeny), przy czym każdy token jest oddzielany dowolnym znakiem z tokenu. a „vs” zawiera dwie postacie
mikewasmike

1
to byłaby lepsza odpowiedź, gdybyś dołączył wyjaśnienie lub przykład. jak to jest, to raczej komentarz ...
billynoah

8

Po prostu możesz użyć następującego kodu:

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


2

Robię to w ten sposób ...

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);
}

to jest to, czego szukałem
Manojkiran.A

2

Co powiesz na to?

/**
 * 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;
}

W twoim przypadku powinieneś użyć Array dla parametru $ delimiters. Wtedy można użyć wielu znaków jako jednego separatora.

Jeśli nie interesują Cię końcowe spacje w wynikach, możesz usunąć array_map('trim', [...] )część w wierszu zwracania. (Ale nie wygłupiaj się w tym przypadku. Zachowaj preg_splitw nim).

Wymagana wersja PHP: 5.3.0 lub nowsza.

Możesz to przetestować tutaj


1

Będziesz miał pewne problemy (co, jeśli masz na przykład ten ciąg: "vs @ jabłka") używając tej metody rozdzielania, ale jeśli zaczniemy od stwierdzenia, że ​​przemyślałeś to i naprawiłeś wszystkie możliwe kolizje, można po prostu zastąpić wszystkich wystąpień $delimiter[1]do $delimiter[n]z $delimiter[0], a następnie podzielone na tej pierwszej?


1

Jeśli twoim separatorem są tylko znaki, możesz użyć strtok, który wydaje się bardziej pasować tutaj. Zauważ, że musisz użyć go z whilepętlą, aby osiągnąć efekty.


0

To zadziała:

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

Jak widać, najpierw skleja eksplodowane części \ n \ r ze spacją, a następnie ponownie je rozdziela, tym razem zabierając ze sobą spacje.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.