2016-12-31 11 views
0

Это конкретный вариант часто повторяющегося вопроса, но, как бы я ни старался, я не мог найти эту точную ситуацию в любом месте Stack Overflow.Не повторяющаяся комбинация конкретного счета в PHP

Короче говоря, я хочу взять массив так:

$days[0] = 'Monday'; 
$days[1] = 'Tuesday'; 
$days[2] = 'Thursday'; 

(. $ Дней может содержать любое количество и сочетание пяти рабочих дней недели)

И затем, с учетом определенного значения $numberOfDays (который, конечно, должен быть не менее 1 и не более, чем счет $days), мне нужен массив, содержащий все возможные комбинации $ days с числом $ numberOfDays дней.

Например:

$days[0] = 'Monday'; 
$days[1] = 'Tuesday'; 
$days[2] = 'Thursday'; 

$numberOfDays = 2; 

$dayCombinations = getDayCombinations($days, $numberOfDays); 

Выход:

$dayCombinations[0] = array("Monday", "Tuesday"); 
$dayCombinations[1] = array("Monday", "Thursday"); 
$dayCombinations[2] = array("Tuesday", "Thursday"); 

Обратите внимание, что эти комбинации, а не перестановки, так что порядок не имеет значения.

Если это поможет, я нашел эту функцию here: Он хорошо работает, но включает в себя повторы и базируется строки вместо массива (что последняя часть является работоспособным, не имеет большого значения, но повторы часть действительно беспорядок для меня).

function sampling($chars, $size, $combinations = array()) { 

    # if it's the first iteration, the first set 
    # of combinations is the same as the set of characters 
    if (empty($combinations)) { 
     $combinations = $chars; 
    } 

    # we're done if we're at size 1 
    if ($size == 1) { 
     return $combinations; 
    } 

    # initialise array to put new values in 
    $new_combinations = array(); 

    # loop through existing combinations and character set to create strings 
    foreach ($combinations as $combination) { 
     foreach ($chars as $char) { 
      $new_combinations[] = $combination . $char; 
     } 
    } 

    # call same function again for the next iteration 
    return sampling($chars, $size - 1, $new_combinations); 
} 

UPDATE: Я пытался обернуть строку присваивая $new_combinations с условной, чтобы помочь; это не имело никакого эффекта, хотя я не уверен, почему. Все комбинации все еще проходят, даже с повторениями.

function sampling($chars, $size, $combinations = array()) { 

    # if it's the first iteration, the first set 
    # of combinations is the same as the set of characters 
    if (empty($combinations)) { 
     $combinations = $chars; 
    } 

    # we're done if we're at size 1 
    if ($size == 1) { 
     return $combinations; 
    } 

    # initialise array to put new values in 
    $new_combinations = array(); 

    # loop through existing combinations and character set to create strings 
    foreach ($combinations as $combination) { 
     foreach ($chars as $char) { 
      if (strpos($combination, $char) === FALSE) { 
       echo "Char $char not found in Combination $combination<br>"; 
       $new_combinations[] = $combination . $char; 
      } 
     } 
    } 

    # call same function again for the next iteration 
    return sampling($chars, $size - 1, $new_combinations); 
} 

Выход там возвращает странности, как:

Char 2 not found in Combination 2 
Char 3 not found in Combination 23 

И так далее.

Спасибо за помощь!

Alex

+1

что вы имеете в виду повторения? Дублирует правильно. Вы можете попробовать 'array_unique ($ dayCombinations)', чтобы удалить их, не будучи уверенным, что он работает с массивами в качестве значения. Или другим способом использовать комбинацию в качестве ключа, например '$ dayCombinations ['Monday-Tuesday'] = array (« Понедельник »,« Вторник »);« тогда они естественным образом уникальны, пока дни находятся в одном и том же порядок для ключа. – ArtisticPhoenix

+0

Добавьте 'if (! In_array ($ item, $ сочетание))' вокруг '$ new_combinations []' назначение. – Barmar

+0

Бармар, я на самом деле пытаюсь это прямо сейчас. Внутри функции выборки $ сочетание и $ char являются строками, поэтому я пытаюсь использовать strpos. Хотя по какой-то причине это не удавалось. Сейчас я обновляю главный пост, чтобы отразить его. –

ответ

2

Это в основном та же самая структура, просто проверить, если на следующий день уже в комбинации, прежде чем добавить.

function sampling($days, $size, $combinations = array()) { 

    # if it's the first iteration, the first set 
    # of combinations is the same as the set of days 
    if (empty($combinations)) { 
     $combinations = array_map(function($day) { return array($day); }, $days); 
    } 

    # we're done if we're at size 1 
    if ($size == 1) { 
     return $combinations; 
    } 

    # initialise array to put new values in 
    $new_combinations = array(); 

    # loop through existing combinations and character set to create strings 
    foreach ($combinations as $combination) { 
     foreach ($days as $day) { 
      if (!in_array($day, $combination)) { 
       $new_combination = $combination; 
       $new_combination[] = $day; 
       $new_combinations[] = $new_combination; 
      } 
     } 
    } 

    # call same function again for the next iteration 
    return sampling($days, $size - 1, $new_combinations); 
} 

DEMO

+0

Мне нравится идея (преобразование ее в массивы, чтобы сделать ее проще). Только проблема, которую я вижу, заключается в том, что это перестановки, а не комбинации (например, мы получаем «понедельник, вторник» как один ответ и «вторник, понедельник» как другой). Я посмотрю, смогу ли я понять это в вашем коде, но если вы видите это, какие-то быстрые изменения для этого? Благодаря! –

+0

Я смог исправить эту часть после вызова, добавив это после, хотя было бы немного лучше и эффективнее делать это, если бы он сам функционировал. \t $ daycombinations = выборка ($ dayslisted, $ daysperweek); \t Foreach ($ daycombinations AS $ ключ => $ daycombination) \t { \t \t рода ($ daycombination); \t \t, если (in_array ($ daycombination, $ daycombinations)) {$ (в отключенном daycombinations [$ ключ]);} \t \t еще {$ daycombinations [$ ключ] = $ daycombination;}} \t –

0

Спекуляция от ответа Barmar, который вернулся перестановкам вместо комбинаций, я добавил еще два строки кода после вызова функции, чтобы избавиться от ненужных перестановок. Вероятно, это более эффективный способ, но для размеров массивов я смотрю, что это незначительно. См. Последние две строки ниже.

function sampling($days, $size, $combinations = array()) { 

    # if it's the first iteration, the first set 
    # of combinations is the same as the set of days 
    if (empty($combinations)) { 
     $combinations = array_map(function($day) { return array($day); }, $days); 
    } 

    # we're done if we're at size 1 
    if ($size == 1) { 
     return $combinations; 
    } 

    # initialise array to put new values in 
    $new_combinations = array(); 

    # loop through existing combinations and character set to create strings 
    foreach ($combinations as $combination) { 
     foreach ($days as $day) { 
      if (!in_array($day, $combination)) { 
       $new_combination = $combination; 
       $new_combination[] = $day; 
       $new_combinations[] = $new_combination; 
      } 
     } 
    } 

    # call same function again for the next iteration 
    return sampling($days, $size - 1, $new_combinations); 
} 

$combinations = getDayCombinations($days, $numberOfDays); 

for ($round=0;$round<count($combinations);$round++){sort($combinations[$round]);} 
    $combinations = array_values(array_map("unserialize", array_unique(array_map("serialize", $combinations)))); 

 Смежные вопросы

  • Нет связанных вопросов^_^