PHP итерирует по многомерному массиву, подсчитывает строки внутри и сбрасывает их в зависимости от количества

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

Я уже пробовал довольно грязную комбинацию array_search, array_count_values ​​и strpos в цикле N^N, но это занимает много времени, и результаты ошибочны...

Это Массив, я пытаюсь переделать

array(2) {
  [0]=>
  array(13) {
    ["id"]=>
    string(6) "1234"
    ["name"]=>
    string(28) "aa"
    ["productcategory"]=>
    string(30) "Branch1^^subbranch1"
    ["streamID"]=>
    int(0)
    ["streamContext"]=>
    string(16) "static"
    ["prio"]=>
    string(3) "100"
  }
  [1]=>
  array(11) {
    ["id"]=>
    string(6) "9876"
    ["name"]=>
    string(30) "bb"
    ["productcategory"]=>
    string(66) "Branch1^^subbranch2"
    ["streamID"]=>
    int(0)
    ["streamContext"]=>
    string(16) "static"
    ["prio"]=>
    string(3) "100"
  }
}

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

Ребята, можете ли вы помочь мне с этим?

3 ответа

Решение

Да, мне приходилось иметь дело с чем-то похожим. Если вы смотрите на массив размером около 200, то создание цикла счетчика должно быть слишком медленным, а затем сбросить значения исходного массива на основе этих счетчиков. Я предоставил шаблон для размышления, чтобы понять, в каком направлении вы находитесь.

Создает копию массива, затем считает productcategoryКонечно, я предполагаю, что category^^subcategory это количество, которое вы ищете.

<?php

$your_array = array(
    array(
        array(
                "id" => "1234",
                "name" => "aa",
                "productcategory" => "Branch1^^subbranch1",
                "streamID" => '',
                "streamContext" => "static",
                "prio" => "100",
        ),
        array(
                "id" => "9876",
                "name" => "bb",
                "productcategory" => "Branch1^^subbranch1",
                "streamID" => '',
                "streamContext" => "static",
                "prio" => "100",
        ),
        array(
                "id" => "9876",
                "name" => "bb",
                "productcategory" => "Branch1^^subbranch3",
                "streamID" => '',
                "streamContext" => "static",
                "prio" => "100",
        ),
        array(
                "id" => "9876",
                "name" => "bb",
                "productcategory" => "Branch1^^subbranch2",
                "streamID" => '',
                "streamContext" => "static",
                "prio" => "100",
        ),
        array(
                "id" => "9876",
                "name" => "bb",
                "productcategory" => "Branch1^^subbranch3",
                "streamID" => '',
                "streamContext" => "static",
                "prio" => "100",
        ),
        array(
                "id" => "9876",
                "name" => "bb",
                "productcategory" => "Branch1^^subbranch1",
                "streamID" => '',
                "streamContext" => "static",
                "prio" => "100",
        ),
    ),
);




$counters = array();
$limit = 1; // whatever the limit is that you want
foreach ($your_array as $index => $array) {
    for ($i = 0; $i < count($array); $i++) {
        if (!isSet($counters[$array[$i]['productcategory']])) {
            $counters[$array[$i]['productcategory']] = 0;
        }
        $counters[$array[$i]['productcategory']]++;
        if ($counters[$array[$i]['productcategory']] > $limit) {
            unset($your_array[$index][$i]);
        }
    }
}

print '<pre>' . print_r($counters, true) . '</pre>';
print '<pre>' . print_r($your_array, true) . '</pre>';

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

Я не смог использовать подход единого размера, но для дальнейшего использования я поделюсь своим "решением". Это не кажется супер сложным, но это делает работу...

function filter_categories($input, $count) {

        $output = $input;

        $exploded_input = [];
        foreach ($output as $key => $value) {
            $exploded_items = explode("^^", $value["productcategory"]);
            array_push($exploded_input, $exploded_items);
        }
        $sortedbyCategory = [];

        $last_items = [];
        $counted_items = [];
        foreach ($exploded_input as $key => $value) {
            $end = end($value);
            array_push($last_items, $end);
        }

        $counted = array_count_values($last_items);

        foreach ($counted as $key => $value) {
            if($value<=$count) {
                unset($counted[$key]);
            }
        }
        foreach ($counted as $k => $v) {
            for ($i=0; $i < count($input); $i++) { 
                if(strpos($input[$i]["productcategory"], $k)){
                    if($counted[$k] > $count) {
                        $input[$i]["hide"] = true;
                        $counted[$k]--;
                    }

                }

            }
        }
        foreach ($input as $key => $value) {
            if(isset($value["hide"])) {
                unset($input[$key]);
            }
        }

        return $input;
    }

Мой первый вопрос к вам будет "откуда ваши данные?" Если это происходит из базы данных, то я бы порекомендовал вам настроить свой запрос там. Вы можете определенно решить эту проблему в PHP, но по мере роста вашего набора данных потребуется больше и больше времени для циклического перебора набора данных в PHP.

Чтобы решить эту проблему в PHP, я бы порекомендовал вам создать новый массив "product index". Этот массив будет ассоциироваться с именем продукта в качестве ключей, а значения будут содержать массив всех индексов верхнего уровня в массиве набора данных. После того, как вы создали индексный массив, вы можете зациклить его, чтобы найти, какие типы продуктов встречаются в основном наборе данных более 3 раз, и быстро удалить эти элементы.

$productIndex = [];

// Build an index of product categories
foreach($dataset as $i => $row) {
   if (!is_array($productIndex[$row['productcategory']]) {
       $productIndex[$row['productcategory']] = [];
   }
   $productIndex[$row['productcategory']][] = $i;
}

// Search for indexes with > 3 rows
foreach($productIndex as $items) {
    if (count($items) > 3) {
        // Delete said rows
        foreach ($items as $index) {
            unset($dataset[$index]);
        }
    }
}
Другие вопросы по тегам