Избегайте вложенных циклов в PHP - PullRequest
0 голосов
/ 18 февраля 2019

Я пишу метод, который принимает массив $topicNames и массив $app и объединяет каждый $app в $topicNames, как показано ниже

public function getNotificationTopicByAppNames(array $topicNames, array $apps)
    {
        $topics = [];

        foreach ($topicNames as $topicName) {
            foreach ($apps as $app) {
                $topic = $app . '_' . $topicName;

                $topics[] = $topic;
            }
        }

        return $topics;
    }
}

Входные данные и результаткак следующее ...

$topicNames = [
    'one_noti',
    'two_noti',
    'three_noti'
];

$apps = [
    'one_app',
    'two_app'
];

// The return result of the method will be like the following

[
    'one_app_one_noti', 
    'two_app_one_noti',
    'one_app_two_noti', 
    'two_app_two_noti',
    'one_app_three_noti', 
    'two_app_three_noti'
]

У меня вопрос вместо того, чтобы делать вложенные циклы, есть ли другой способ, которым я могу сделать?Почему я хочу избежать вложенных циклов?Потому что в настоящее время у меня есть $topic.Позже я, возможно, захочу добавить languages, locations и т. Д ...

Я знаю, что могу использовать map, reduce, array_walks, each, которые в основном проходят один за другим.Вместо того, какой другой альтернативный способ я могу использовать?Я в порядке, изменяя различные типы данных вместо массива.

Ответы [ 3 ]

0 голосов
/ 18 февраля 2019

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

<?php 

    public function mergeStacks(...$stacks)
    {
        $allStacks = call_user_func_array('array_merge', $stacks);
        return $this->concatString($allStacks);

    }

    private function concatString(&$stack, $index = 0, &$result = [])
    {
        if(count($stack) == 0){
            return '';
        }

        if($index  == count($stack)){
            return $result;
        }



        array_walk($stack, function($value, $key) use($index, &$result, $stack){
            if($key > $index){
                array_push($result, $stack[$index] . '_' . $value);
            }
        });
        $index =  $index + 1;

        return $this->concatString($stack, $index, $result);
    }

И затем, когда вы хотите получить массив, независимо от того, есть ли у вас языки или темы и т. Д., Вы можете просто сделать:

$this->mergeStacks($languages, $topics, $locations, .....);

Где $ languages, $ themes, $ location - это простые массивы.

0 голосов
/ 18 февраля 2019

Вместо того, чтобы принимать только параметр имени темы, попробуйте что-то вроде этого:

function getNotificationTopicByAppNames(array $apps, array ...$names)
{
    $topics = [];
    foreach ($names as $nameArray) {
        foreach ($nameArray as $topicName) {
            foreach ($apps as $app) {
                $topic = $app . '_' . $topicName;

                $topics[] = $topic;
            }
        }
    }

    return $topics;
}



$topicNames = [
    'one_noti',
    'two_noti',
    'three_noti'
];

$languagesNames = [
    'test_en',
    'test_other',
    'test_other2'
];

$apps = [
    'one_app',
    'two_app'
];

print_r(getNotificationTopicByAppNames($apps,$topicNames,$languagesNames));

Вы можете передать любое количество массивов в массив.

0 голосов
/ 18 февраля 2019

Если вы не заботитесь о заказе, вы можете использовать этот

function getNotificationTopicByAppNames(array $topicNames, array $apps)
{
    $topics = [];

    foreach($apps as $app){
        $topics = array_merge($topics, preg_filter('/^/', $app.'_', $topicNames));
    }

    return $topics;
}

print_r(getNotificationTopicByAppNames($topicNames,$apps));

Выход

Array
(
    [0] => one_app_one_noti
    [1] => one_app_two_noti
    [2] => one_app_three_noti
    [3] => two_app_one_noti
    [4] => two_app_two_noti
    [5] => two_app_three_noti
)

Песочница

Вы также можете переключитьсяциклы и использовать $ вместо постфикса вместо префикса.Который оказывается в том же порядке, что и у вас.Я думал о префиксе как способ удалить цикл.Тогда я подумал, почему бы не перевернуть его.

 function getNotificationTopicByAppNames(array $topicNames, array $apps)
{
    $topics = [];

    foreach($topicNames as $topic){
        $topics = array_merge($topics, preg_filter('/$/', '_'.$topic, $apps));
    }

    return $topics;
}

print_r(getNotificationTopicByAppNames($topicNames,$apps));

Вывод

 Array
(
    [0] => one_app_one_noti
    [1] => two_app_one_noti
    [2] => one_app_two_noti
    [3] => two_app_two_noti
    [4] => one_app_three_noti
    [5] => two_app_three_noti
)

Песочница

Хитрость здесь заключается в использовании preg_filter.

http://php.net/manual/en/function.preg-filter.php

preg_filter - Выполните поиск по регулярному выражению и замените

Таким образом, мы ищем с ^ начало или $ конец, который нене поймать ничего, чтобы заменить, а затем мы просто добавим то, что мы хотимЯ использовал это раньше, когда хотел префиксить целый массив чем-то и т. Д.

Я не мог проверить его в классе, поэтому я сделал его обычной функцией, поэтому настройте его по мере необходимости.

Ура!

...