Как без конфликтов назначить все входные значения в массив на основе доступности ключей? - PullRequest
2 голосов
/ 06 мая 2020

Ищу технику заполнения щели. У меня есть 8 "слотов" в виде плоского массива. У меня также есть многомерный массив, где ключи - это субъекты, а значения - это подмассивы, содержащие индексированные элементы (слоты).

Многомерный массив ($emp) может содержать, например, тему Tamil, которая доступна по адресу слоты с 1 по 5 и / или English, который доступен только во время слотов 4, 5 или 6. Все предлагаемые предметы будут иметь набор доступных слотов - даже если доступен только один слот.

Доступность темы:

$emp = array(
    "tamil"   => array(1, 2, 3, 4, 5),
    "english" => array(4, 5, 6),
    "maths"   => array(1, 5, 8),
    "social"  => array(1, 2, 5),
    "pt"      => array(1),
    "hindi"   => array(3, 4, 7)
);

Мне нужно назначить следующим темам точное количество раз - при соблюдении доступности субъекта И без «конфликта слотов» - в моем выходном массиве ($sort):

  • Тамильский 2 раза
  • PT 1 раз
  • Математика 2 раза
  • Социальные 1 раз
  • Хинди 1 раз
  • англи sh 1 раз

Все 8 слотов должны быть заполнены. Все предметы должны встречаться только один раз, за ​​исключением тамильского языка и математики, которые должны встречаться ровно дважды.

Результат может быть:

$slot[3] = 'tamil',
$slot[7] = 'Hindi', 
$slot[6] = 'English',
$slot[1] = 'Pt',
$slot[5] = 'Maths',
$slot[8] = 'Maths',
$slot[4] = 'Tamil',
$slot[2] = 'Social'.

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

for ($i = 1; $i < 9; $i++) {
    $var = $subarray[$i];
    if (count($var) <= 1) { 
        $filledslots[$i] = $var[0];
    } else {
        $empty[$i] = '';
    }
}
$subjects = array_flat($subarray); 
$count_values = array(); 
$subjects = array_diff($subjects, $filledslots);
foreach ($subjects as $value) { 
   $count_values[$value] = 0; 
   foreach ($empty as $key => $val) {
       $res = $subarray[$key];
       if (in_array($value, $res)) {
           $count_values[$value] = $count_values[$value] + 1;
       }
   }
   if ($count_values[$value] == 1) {
       //$filledslots[1] = $count_values[$value];
       foreach ($empty as $key => $val) {
           $res = $subarray[$key]; 
           if (in_array($value, $res)) {
               $filledslots[$key] = $value;
           }
       }
   }
}
print_r(($filledslots)); 

1 Ответ

2 голосов
/ 08 мая 2020

Вот рабочий рекурсивный метод, который вернет первый квалифицирующий набор данных.

Он работает путем удаления элементов из массива «требуемых субъектов» и массива «доступных слотов» при добавлении элементов в «заполненный» slots "массив.

Использование уточняющих значений от array_replace() до pu sh в третьем параметре, доставляемом в рекурсивном вызове, предотвращает нарушение состояния переменной $filledSlots, которая будет продолжать использоваться циклы foreach.

Функция: ( Demo )

function fillSlots($requiredSubjects, $availableSlots, $filledSlots = []) {
    if (!$requiredSubjects) {
        ksort($filledSlots);
        return $filledSlots;
    }
    foreach ($requiredSubjects as $rIndex => $subject) {
        foreach ($availableSlots[$subject] as $sIndex => $slot) {
            if (!isset($filledSlots[$slot])) {
                unset($requiredSubjects[$rIndex], $availableSlots[$subject][$sIndex]);
                $result = fillSlots(
                    $requiredSubjects,
                    $availableSlots,
                    array_replace($filledSlots, [$slot => $subject])
                );
                if ($result) {
                    return $result;
                }
            }
        }
    }
}

Входные переменные:

$subjectSlots = [
    "tamil"   => [1, 2, 3, 4, 5],
    "english" => [4, 5, 6],
    "maths"   => [1, 5, 8],
    "social"  => [1, 2, 5],
    "pt"      => [1],
    "hindi"   => [3, 4, 7]
];
$requiredSubjects = ['tamil', 'tamil', 'pt', 'maths', 'maths', 'social', 'hindi', 'english'];

Чтобы разрешить функция для выполнения в тысячи раз быстрее (я тестировал, потому что мне было любопытно), подготовьте входные данные так, чтобы сначала выполнялись итерации субъектов с меньшим количеством слотов.

Сортировка перед выполнением: ( Посмотреть эффект )

usort($requiredSubjects, function($a, $b) use ($subjectSlots) {
    return $subjectSlots[$a] <=> $subjectSlots[$b];  // sort by length, then by values
});

Первоначальный вызов:

var_export(fillSlots($requiredSubjects, $subjectSlots));

Вывод:

array (
  1 => 'pt',
  2 => 'social',
  3 => 'tamil',
  4 => 'tamil',
  5 => 'maths',
  6 => 'english',
  7 => 'hindi',
  8 => 'maths',
)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...