Как взорвать массив с ключом и значением без foreach в PHP


113

Как я могу превратить такой массив без foreach

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

к такой строке

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

Я implode()уже думал об этом , но это не взрывает ключ.

Если foreach это необходимо, можно ли не вкладывать foreach?

РЕДАКТИРОВАТЬ: я изменил строку


EDIT2 / UPDATE: этот вопрос был задан довольно давно. В то время я хотел написать все в одной строке, чтобы использовать тернарные операторы и вложить встроенные вызовы функций в пользу foreach. Это не было хорошей практикой! Пишите код, который можно читать, краткий он или нет, не имеет большого значения.

В этом случае: включение foreach в функцию будет намного более читабельным и модульным, чем написание однострочника (даже если все ответы отличные!).


Насколько нужен вложенный foreach?
Shubham

Что вы пытаетесь сделать? Почему у вас есть эти ограничения?
Призрак Мадары

это был мой класс базы данных для веб-приложения, которое я создаю, я не хочу, чтобы он выглядел беспорядочно, поскольку он уже заполнен кучей foreach и for-loop вместе
tom91136

1
Этот выбранный ответ - это метод, который вы просили, однако следует отметить, что он критически медленнее и что если вы сохраняете эту информацию через базу данных, он будет намного лучше, чем цикл, и просто использовать json_encode. Приложение A: willem.stuursma.name/2010/11/22/…
Дело

Ответы:


187

и другой способ:

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

или:

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

6
Этот метод - то, о чем просил Автор, но следует отметить, что он критически медленнее и что если вы сохраняете эту информацию через базу данных, он будет намного лучше, чем цикл, и просто использовать json_encode. Приложение A: willem.stuursma.name/2010/11/22/…
Дело

Кажется, что ни одна из ссылок здесь больше не работает, они все. echo "Hello, World!";Должен ли я видеть примеры кода этих функций?
Феликс Ганьон-Гренье,

Этот метод очень легко адаптировать под собственные нужды.
Кабир Хосейн

Я использовал этот метод для создания параметров выбора и заполнения выбранного параметра, и, поскольку оба массива должны быть одного размера, вы можете сделать что-то подобное для второго массива. array_fill(0, $input, 'selected-value-you want-to-check-against');Это создаст массив одинакового размера с одним значением для всех строк.
красенславов

188

Вы можете использовать http_build_query , например:

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

Вывод:

item1=object1, item2=object2 

Демо


6
Никогда не использовал другие параметры http_build_query.
Шиплу Мокаддим

16
+1 Черт, да, я люблю находить такие маленькие самородки добра :)
Бен

8
Остерегайтесь строковой кодировки! Если вы не создаете URL-адрес, возможно, он вам не нужен в вашем массиве ключ и значение
Маттео

8
@Matteo Вы можете обернуть http_build_queryв , urldecodeчтобы избежать этого.
Afterlame

3
Гениальное решение. Это было все, что мне нужно для вывода отладки массива ассоциативных записей.
dixus 01

34

Провёл замеры (100000 итераций), какой самый быстрый способ приклеить ассоциативный массив?

Задача: получить строку из 1000 элементов в следующем формате: «ключ: значение, ключ2: значение2».

У нас есть массив (например):

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

Тест номер один:

Используйте http_build_query и str_replace :

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

Среднее время взрыва 1000 элементов: 0,00012930955084904

Тест номер два:

Используйте array_map и взрывать :

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

Среднее время взрыва 1000 элементов: 0,0004890081976675

Тест номер три:

Использование array_walk и взрывать :

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

Среднее время взрыва 1000 элементов: 0,0003874126245348

Тест номер четыре:

Используйте foreach :

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

Среднее время взрыва 1000 элементов: 0,00026632803902445

Могу сделать вывод, что лучший способ склеить массив - использовать http_build_query и str_replace


4
$s = ''; foreach ($array as $k=>$v) { if ($s !== null) { $s .= ','; } $s .= "{$k}:{$v}"; }превосходит всех остальных.
Fleshgrinder

1
На стенде http_build_query отсутствует urldecode для сравнения с другими.
nickl-

Другой вариант:substr(str_replace('"', '', json_encode($headers)), 1, -1);
nickl-

1
ВНИМАНИЕ: он изменяет ваши значения, если в нем есть место. http_build_queryЗаменяет пробелы со знаком плюс ( +) характер.
Эрфун

9

Я бы использовал serialize()или json_encode().

Хотя он не даст вам точной строки результата, которую вы хотите, было бы намного проще кодировать / хранить / извлекать / декодировать позже.


3

Использование 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
Мне нравится подход array_walk, но я не понимаю, почему люди предлагают использовать create_functionвместо того, чтобы просто использовать анонимную функцию?
Rikki

@Rikki Совместимость!
Шиплу Мокаддим

Ах! Я не понимал, что это вещь PHP4!
Rikki

@Rikki Нет . Это до PHP 5.3. Анонимная функция впервые появилась в PHP 5.3
Шиплу Мокаддим

Но он появился в PHP 4.0.1, как и PHP4. Семантика ... Добавление такой важной функции, как анонимные функции, в обновление второстепенной версии - это странно.
Rikki

2

+ Изменить

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

если вы хотите вернуть всю строку без последнего клея $

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

И использование:

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

Я понимаю, что это действительная альтернатива написанию цикла foreach каждый раз. ОБНОВЛЕНО;)
tony gil

2

В целях отладки. Рекурсивно записывает массив вложенных массивов в строку. Используется foreach. Функция хранит символы национального языка.

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

Вы также можете использовать PHP array_reduce ,

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

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

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

1

Для создания mysql, где условия из массива

$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

Также существуют var_export и print_r, более известные для вывода отладочной информации, но обе функции могут принимать необязательный аргумент для возврата вместо этого строки.

Используя пример из вопроса в качестве данных.

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

Использование print_rдля преобразования массива в строку

Это выведет удобочитаемое представление переменной.

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

Выведет:

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

Использование var_exportдля преобразования массива в строку

Будет выведено строковое представление переменной на php.

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

Выведет:

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

Поскольку это действительный php, мы можем его оценить.

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

Выходы:

bool(true)

0

Вот простой пример с использованием класса:

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

}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.