Jak implodować tablicę z kluczem i wartością bez foreach w PHP


112

Bez foreach , jak mogę zmienić taką tablicę

array("item1"=>"object1", "item2"=>"object2",......."item-n"=>"object-n");

do takiego ciągu

item1='object1', item2='object2',.... item-n='object-n'

Już o tym myślałem implode(), ale nie powoduje implozji klucza.

Jeśli za każdym razem jest to konieczne, czy można nie zagnieżdżać wszystkich?

EDYCJA: Zmieniłem ciąg


EDIT2 / UPDATE: To pytanie zostało zadane dość dawno temu. W tamtym czasie chciałem napisać wszystko w jednej linii, więc użyłem operatorów trójskładnikowych i zagnieżdżonych wywołań funkcji na korzyść foreach. To nie była dobra praktyka! Pisanie kodu, który jest czytelny, czy jest zwięzły, czy nie, nie ma większego znaczenia.

W tym przypadku: umieszczenie foreach w funkcji będzie dużo bardziej czytelne i modularne niż pisanie tekstu w jednej linijce (chociaż wszystkie odpowiedzi są świetne!).


Jak zagnieżdżone byłoby konieczne?
Shubham,

Czego próbujesz? Dlaczego masz te ograniczenia?
Madara's Ghost

to była moja klasa bazy danych dla aplikacji internetowej, którą tworzę, nie chcę, aby wyglądała niechlujnie, ponieważ jest już wypełniona
wieloma pętlami

1
Ta wybrana odpowiedź to metoda, o którą prosiłeś, jednak należy zauważyć, że jest ona znacznie wolniejsza i że jeśli przechowujesz te informacje w bazie danych, byłoby znacznie lepsze zarówno od pętli, jak i po prostu użyć json_encode. Załącznik A: willem.stuursma.name/2010/11/22/...
Sprawa,

Odpowiedzi:


187

i w inny sposób:

$input = array(
    'item1'  => 'object1',
    'item2'  => 'object2',
    'item-n' => 'object-n'
);

$output = implode(', ', array_map(
    function ($v, $k) {
        if(is_array($v)){
            return $k.'[]='.implode('&'.$k.'[]=', $v);
        }else{
            return $k.'='.$v;
        }
    }, 
    $input, 
    array_keys($input)
));

lub:

$output = implode(', ', array_map(
    function ($v, $k) { return sprintf("%s='%s'", $k, $v); },
    $input,
    array_keys($input)
));

6
Ta metoda jest tym, o co prosił autor, ale należy zauważyć, że jest ona znacznie wolniejsza i że jeśli przechowujesz te informacje w bazie danych, byłoby znacznie lepsze zarówno od pętli, jak i po prostu użyć json_encode. Załącznik A: willem.stuursma.name/2010/11/22/…
Sprawa,

Żaden z linków tutaj nie wydaje się już działać, wszystkie echo "Hello, World!";Czy mam zobaczyć przykłady kodu tych funkcji?
Félix Gagnon-Grenier

Ta metoda jest bardzo łatwa do dostosowania zgodnie z własnym zapotrzebowaniem.
Kabir Hossain

Używałem tej metody do budowania opcji zaznaczania i wypełniania wybranej opcji, a ponieważ obie tablice muszą mieć ten sam rozmiar, możesz zrobić coś takiego dla drugiej tablicy. array_fill(0, $input, 'selected-value-you want-to-check-against');Spowoduje to wygenerowanie tablicy tego samego rozmiaru z jedną wartością dla wszystkich wierszy.
krasenslavov

188

Możesz użyć http_build_query , na przykład:

<?php
  $a=array("item1"=>"object1", "item2"=>"object2");
  echo http_build_query($a,'',', ');
?>

Wynik:

item1=object1, item2=object2 

Próbny


6
Nigdy nie korzystałem z innych parametrów http_build_query.
Shiplu Mokaddim,

16
+1 do diabła, tak, uwielbiam znajdować takie małe bryłki dobra :)
Ben

8
Uważaj na kodowanie ciągów! Jeśli nie tworzysz adresu URL, być może nie chcesz go w swoim kluczu i wartości tablicy
Matteo

8
@Matteo Można owinąć http_build_queryw urldecodecelu uniknięcia go.
Afterlame

3
Genialne rozwiązanie. To było wszystko, czego potrzebowałem do debugowania danych wyjściowych z tablicy am assoc.
dixus

33

Wydałem pomiary (100000 iteracji), jaki jest najszybszy sposób na przyklejenie tablicy asocjacyjnej?

Cel: uzyskanie wiersza zawierającego 1000 pozycji w następującym formacie: „klucz: wartość, klucz2: wartość2”

Mamy tablicę (na przykład):

$array = [
    'test0' => 344,
    'test1' => 235,
    'test2' => 876,
    ...
];

Test numer jeden:

Użyj http_build_query i str_replace :

str_replace('=', ':', http_build_query($array, null, ','));

Średni czas implodowania 1000 elementów: 0,00012930955084904

Test numer dwa:

Użyj array_map i implode :

implode(',', array_map(
        function ($v, $k) {
            return $k.':'.$v;
        },
        $array,
        array_keys($array)
    ));

Średni czas implodowania 1000 elementów: 0,0004890081976675

Test numer trzy:

Użyj array_walk i implode :

array_walk($array,
        function (&$v, $k) {
            $v = $k.':'.$v;
        }
    );
implode(',', $array);

Średni czas implodowania 1000 elementów: 0,0003874126245348

Test numer cztery:

Użyj dla każdego :

    $str = '';
    foreach($array as $key=>$item) {
        $str .= $key.':'.$item.',';
    }
    rtrim($str, ',');

Średni czas implodowania 1000 elementów: 0,00026632803902445

Mogę stwierdzić, że najlepszym sposobem na przyklejenie tablicy - użyj http_build_query i str_replace


4
$s = ''; foreach ($array as $k=>$v) { if ($s !== null) { $s .= ','; } $s .= "{$k}:{$v}"; }przewyższa wszystkie inne.
Fleshgrinder

1
W stanowisku http_build_query brakuje kodu urldkodu, aby można go było porównać z innymi.
nickl-

Inna opcja:substr(str_replace('"', '', json_encode($headers)), 1, -1);
nickl-

1
UWAGA: Zmienia wartości, jeśli jest w nim miejsce. http_build_queryZastępuje spacje z plus ( +) charakter.
Erfun

9

Użyłbym serialize()lub json_encode().

Chociaż nie da to dokładnego ciągu wynikowego, który chcesz, byłoby znacznie łatwiej zakodować / zapisać / pobrać / zdekodować później.


3

Korzystanie z array_walk

$a = array("item1"=>"object1", "item2"=>"object2","item-n"=>"object-n");
$r=array();
array_walk($a, create_function('$b, $c', 'global $r; $r[]="$c=$b";'));
echo implode(', ', $r);

IDEONE


1
Podoba mi się podejście array_walk, ale nie rozumiem, dlaczego ludzie sugerują używanie create_functionzamiast zwykłej funkcji anonimowej?
Rikki

@Rikki Compatibility!
Shiplu Mokaddim

Ach! Nie zdawałem sobie sprawy, że to kwestia PHP4!
Rikki

@Rikki nr . Jego rzecz sprzed PHP 5.3. Funkcja anonimowa pojawiła się po raz pierwszy w PHP 5.3
Shiplu Mokaddim

Ale został wprowadzony w PHP 4.0.1, więc jest rzeczą PHP4. Semantyka ... Dodanie funkcji tak ważnej jak funkcje anonimowe w pomniejszej aktualizacji wersji jest dziwaczne.
Rikki

2

Zmiana

-    return substr($result, (-1 * strlen($glue)));
+    return substr($result, 0, -1 * strlen($glue));

jeśli chcesz przywrócić cały String bez ostatniego kleju $

function key_implode(&$array, $glue) {
    $result = "";
    foreach ($array as $key => $value) {
        $result .= $key . "=" . $value . $glue;
    }
    return substr($result, (-1 * strlen($glue)));
}

I użycie:

$str = key_implode($yourArray, ",");

Rozumiem, że jest to dobra alternatywa dla pisania pętli foreach za każdym razem. ZGŁOSOWANO;)
tony gil

2

Do celów debugowania. Rekursywnie zapisuje tablicę zagnieżdżonych tablic do ciągu. Używane foreach. Funkcja przechowuje znaki języka narodowego.

function q($input)
{
    $glue = ', ';
    $function = function ($v, $k) use (&$function, $glue) {
        if (is_array($v)) {
            $arr = [];
            foreach ($v as $key => $value) {
                $arr[] = $function($value, $key);
            }
            $result = "{" . implode($glue, $arr) . "}";
        } else {
            $result = sprintf("%s=\"%s\"", $k, var_export($v, true));
        }
        return $result;
    };
    return implode($glue, array_map($function, $input, array_keys($input))) . "\n";
}

2

Możesz również użyć funkcji array_reduce w PHP ,

$a = ['Name' => 'Last Name'];

function acc($acc,$k)use($a){ return $acc .= $k.":".$a[$k].",";}

$imploded = array_reduce(array_keys($a), "acc");

1

Do tworzenia mysql, gdzie warunki z tablicy

$sWheres = array('item1'  => 'object1',
                 'item2'  => 'object2',
                 'item3'  => 1,
                 'item4'  => array(4,5),
                 'item5'  => array('object3','object4'));
$sWhere = '';
if(!empty($sWheres)){
    $sWhereConditions = array();
    foreach ($sWheres as $key => $value){
        if(!empty($value)){
            if(is_array($value)){
                $value = array_filter($value); // For remove blank values from array
                if(!empty($value)){
                    array_walk($value, function(&$item){ $item = sprintf("'%s'", $item); }); // For make value string type 'string'
                    $sWhereConditions[] = sprintf("%s in (%s)", $key, implode(', ', $value));
                }
            }else{
                $sWhereConditions[] = sprintf("%s='%s'", $key, $value);
            }
        }
    }
    if(!empty($sWhereConditions)){
        $sWhere .= "(".implode(' AND ', $sWhereConditions).")";
    }
}
echo $sWhere;  // (item1='object1' AND item2='object2' AND item3='1' AND item4 in ('4', '5') AND item5 in ('object3', 'object4'))

1

Istnieją również opcje var_export i print_r, które są bardziej znane z drukowania wyników debugowania, ale obie funkcje mogą przyjmować opcjonalny argument, aby zamiast tego zwrócić ciąg.

Na podstawie przykładu z pytania jako danych.

$array = ["item1"=>"object1", "item2"=>"object2","item-n"=>"object-n"];

Używanie print_rdo przekształcenia tablicy w ciąg

Spowoduje to wyświetlenie czytelnej dla człowieka reprezentacji zmiennej.

$string = print_r($array, true);
echo $string;

Wyświetli:

Array
(
    [item1] => object1
    [item2] => object2
    [item-n] => object-n
)

Używanie var_exportdo przekształcenia tablicy w ciąg

Który wyświetli reprezentację zmiennej w postaci ciągu php.

$string = var_export($array, true);
echo $string;

Wyświetli:

array (
  'item1' => 'object1',
  'item2' => 'object2',
  'item-n' => 'object-n',
)

Ponieważ jest to poprawny php, możemy go ocenić.

eval('$array2 = ' . var_export($array, true) . ';');
var_dump($array2 === $array);

Wyjścia:

bool(true)

0

Oto prosty przykład, używając class:

$input = array(
    'element1'  => 'value1',
    'element2'  => 'value2',
    'element3' =>  'value3'
);

echo FlatData::flatArray($input,', ', '=');

class FlatData
{

    public static function flatArray(array $input = array(), $separator_elements = ', ', $separator = ': ')
    {
        $output = implode($separator_elements, array_map(
            function ($v, $k, $s) {
                return sprintf("%s{$s}%s", $k, $v);
            },
            $input,
            array_keys($input),
            array_fill(0, count($input), $separator)
        ));
      return $output;
    }

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