Взаимное сопряжение Excel - PullRequest
0 голосов
/ 28 мая 2020

Как я могу объединить элементы списка в пары так, чтобы если пара элемента 'a' была членом 'b', то пара 'b' была 'a' в MS Excel?

В идеале, при каждом вычислении соединение выбирается случайным образом.

Попытка:

1) У меня есть список имен в столбце (столбец B).

2) Я поместил натуральные числа до длины списка в столбец A:

=ROW(B2)-1

3) Случайные числа в столбце C:

=RAND()

4) Я упорядочил случайные числа в столбце D.

=RANK(C2, $C$2:$C$178)

Таким образом, у меня есть два порядка. Порядок появления в столбце A и случайный порядок в столбце D.

Однако, например, строка за строкой «пара из 11», в свою очередь, не имеет 11 в качестве пары. Как добиться взаимного спаривания? Если 11 в паре с 27, мне нужно, чтобы 27 было также в паре с 11.

(затем я могу VLOOKUP, чтобы вытащить имена.)

=VLOOKUP(D2,$A$2:$B$178,2,0)

EDIT:

Сильфон - мой результат. Вы можете видеть, что «c» - это пара «а», а «а» - это , а не пара «c». (Столбец F проверяет, связан ли кто-то с самим собой.)

My Pairing

Итак, в основном в столбце вывода E я беру имя, соответствующее случайному ранжирование. Хотелось бы как-нибудь завязать взаимные пары.

Ответы [ 2 ]

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

Вот еще один подход. В вашем столбце E у вас есть перестановка имен. Оставьте это как промежуточный столбец. В данном случае это c,b,d,a. Просто сопоставьте c с b и d с a. Index и Match можно использовать для извлечения пар следующим образом:

enter image description here

Ключевой формулой в F2 является

=IF(MOD(MATCH(B2,$E$2:$E$5,0),2) = 0,INDEX($E$2:$E$5,MATCH(B2,$E$2:$E$5,0)-1),INDEX($E$2:$E$5,MATCH(B2,$E$2:$E$5,0)+1))

Формулы в столбцах D, E в точности такие, как вы их указали.

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

Чтобы случайным образом объединить такие числа в пары, вам нужно , чтобы учесть, какие числа уже были выбраны. Затем , вам нужно случайным образом выбрать из оставшихся чисел.

Итак, чтобы сделать это, я собираюсь отбросить ваш столбец «Случайное число» и вычислить «Ранг» напрямую. Для начала проверяем, есть ли у этого элемента уже пара. Все, что мы будем делать, это использовать MATCH, чтобы узнать, существует ли эта запись ранее в столбце D, и (если да) используйте INDEX, чтобы найти, с каким номером она была связана:

=INDEX(A:A, MATCH(A2, D$1:D1, 0))

Весь код, кроме последнего примера, будет записан для ячейки D2

Если эта запись уже была объединена в пары, она вернет ошибку. В противном случае он вернет совпадение. Если совпадений не найдено, нам нужно выбрать одно случайным образом. Это условие просто IFERROR:

=IFERROR(INDEX(A:A, MATCH(A2, D$1:D1, 0)), <FIND_RANDOM_RANK>)

Есть несколько способов получить ранг случайным образом, но я собираюсь использовать AGGREGATE и RANDBETWEEN. Мы создадим список невыбранных номеров в AGGREGATE (например, {2, 3, 7, 8, 12}), а затем используем RANDBETWEEN для выбора позиции случайным образом (например, RANDBETWEEN(1, 5), потому что есть 5 элементов на выбор). Наш список будет состоять из номеров строк, поэтому нам нужно будет преобразовать их в порядковые номера с помощью INDEX.

=IFERROR(INDEX(A:A, MATCH(A2, D$1:D1, 0)), INDEX(A:A, <FIND_RANDOM_ROW>))

Поскольку наш номер строки - это числа, поэтому мы можем положить их по порядку и выберите k th SMALL est

AGGREGATE(15, 6, <NUMBER_LIST>, RANDBETWEEN(1, <NUMBER_OF_ITEMS>))

Количество элементов будет общим количеством, за вычетом того, сколько элементов уже было парные. Количество уже сопряженных элементов будет равно количеству элементов над нами в списке, ПЛЮС, однако многие из них связаны с элементами ниже.

AGGREGATE(15, 6, <NUMBER_LIST>, RANDBETWEEN(1, COUNTA(A:A)-(Row()+COUNTIF(D$1:D1,">"&A2))))

В списке номеров мы можем использовать #DIV0! ошибки, чтобы пометить элементы как исключенные. Мы исключаем их, если они уже были объединены в пары: либо над нами в списке, либо в паре с элементом над нами в списке.

ROW(A:A) / ((Row(A:A)>Row()) * (COUNTIF(D$1:D1,A:A)=0))

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

Для этого, мы можем использовать INDEX и COUNTA, чтобы определить, сколько строк записей у нас есть. Это означает, например, изменение A:A на A$1:INDEX(A:A,COUNTA(A:A)). Если у вас 10 строк данных, это будет go A$1:INDEX(A:A,COUNTA(A:A))A$1:INDEX(A:A,10)A$1:A10, что в 100000 раз меньше данных для обработки!

ROW(A$1:INDEX(A:A,COUNTA(A:A))) / ((Row(A$1:INDEX(A:A,COUNTA(A:A)))>Row()) * (COUNTIF(D$1:D1,A:A)=0))    

Теперь , мы можем сложить все это вместе, чтобы получить окончательное уравнение:

=IFERROR(INDEX(A:A, MATCH(A2, D$1:D1, 0)), INDEX(A:A,AGGREGATE(15, 6, ROW(A$1:INDEX(A:A,COUNTA(A:A))) / ((ROW(A$1:INDEX(A:A,COUNTA(A:A)))>ROW()) * (COUNTIF(D$1:D1,A:A)=0)), RANDBETWEEN(1, COUNTA(A:A)-(ROW()+COUNTIF(D$1:D1,">"&A2))))))

Это даст нам наш соответствующий рейтинг. Все, что нам нужно сделать, это быстро VLOOKUP в столбцах A и B, чтобы определить, что это за имя:

=VLOOKUP(D2,A:B,2,FALSE)

Этот код предназначен для ячейки E2

(В целом, этот код будет намного более эффективным, если ваш список имеет фиксированный размер, и вы можете затем заменить биты COUNTA(A:A) и A$1:INDEX(A:A,COUNTA(A:A)) правильными числами и ссылки на ячейки напрямую, например 5 и A$1:A$5)

...