Равномерное перемешивание списка почтовых адресов по доменам

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

Например:

пусть будет список,

[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

Результат должен быть

[email protected]
[email protected]
[email protected]
[email protected]
[email protected]
[email protected]

Исходный список не сортируется по домену, как в примере, но может быть отсортирован по домену, если это может помочь. Каким будет эффективный алгоритм (однопроходный / двухпроходный?) Для этого?

радж

Хорошо, могу я спросить Почему, ты хочешь их перемешать? Если нужно равномерно распределять почтовый трафик по каждому из доменов, то не делайте этого. Более эффективно доставлять почту для одного и того же домена одновременно, поскольку они могут совместно использовать SMTP-соединение.

Alnitak 12.11.2008 18:07
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
1
207
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

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

Если в этом есть смысл.

Следующий код полностью НЕПРОВЕРЕННЫЙ, и я знаю, что во втором цикле есть куча вещей, но это было быстрее, чем пытаться объяснить дальше.

$sortedList = array();
$tempList
$emailList = array('[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]', '[email protected]');

$emailCount = 0;
foreach ( $emailList as $email ) {
    list($username, $domain) = explode('@', $email);
    $tempList[$domain][] = $user;
    $emailCount++;
}

for ( $i = 0; $i < $emailCount; $i++ ) {
    $listIndex = $i % count($tempList);
    if ( !empty($tempList[$listIndex]) ) {
        $sortedList[] = $tempList[$listIndex][0];
        unset($tempList[$listIndex][0]);
    } else {
        unset$tempList[$listIndex]);
    }
}

По сути, для каждого адреса электронной почты поместите адрес в связанный список для данного домена. Это операция O (n), затем создание нового сбалансированного списка - это еще одна операция примерно O (n) путем циклического перебора списков доменов.

Это примерно двухпроходная сложность, как и было заказано.

Остерегайтесь ответов, которые предполагают, что количество адресов электронной почты в домене одинаково (или похоже).

Я попытался решить, по сути, ту же проблему, и она получила много обсуждений в моем блоге: Первая статья, Вторая статья

Мы не нашли быстрого и оптимального решения, но самое быстрое и близкое решение (включая исходный код Perl) взят из комментария Аристотель Пагальцис.

Престижность Аристотелю.

Ответ принят как подходящий

Вот мое решение этой проблемы. Учитывая ввод вроде

[["A", 13], ["B", 5], ["C", 3], ["D", 1]] 

На выходе

AABABAACABAACABAACABAD

Исходный код программы на Ruby:

require "pp"

def shuffle (total, num)
  ret_arr = Array.new
  intervel = total/num.to_f
  0.upto(num-1) do |i|
    val = i * intervel
    ret_arr << val.floor
  end
  return ret_arr
end

freq_table = [["A", 13], ["B", 5], ["C", 3], ["D", 1]]

pp freq_table
total = 0
freq_table.collect {|i| total += i[1] }
final_array = Array.new(total,0)
print  final_array.to_s + "\n\n"
placed = 0

freq_table.each do |i|
  placements =  shuffle(total - placed, i[1])
  placements.each do |j|
    free_index = -1
    0.upto final_array.size do |k|
      free_index += 1 if (final_array[k] == 0 || final_array[k] == i[0])
      if j == free_index
        final_array[k] = i[0]
        break
      end
    end
  end
  print "Placing #{i[1]} #{i[0]}s over #{total - placed} positions\n"
  pp placements
  print  final_array.to_s + "\n\n"
  placed += i[1]
end

Идея состоит в том, чтобы взять алфавит с наибольшей частотой и сначала распределить его по массиву, размер которого равен общему количеству всех элементов. Затем распределите алфавит со второй по частоте раздачей и распределите его по свободным местам и так далее.

Если у вас есть вопросы, дайте мне знать, и я буду рад ответить.

радж

Другие вопросы по теме