Подтвердить что ты не робот

Можно ли сортировать два списка (которые ссылаются друг на друга) точно так же?

Хорошо, это может быть не самая умная идея, но мне было немного любопытно, если это возможно. Скажем, у меня есть два списка:

list1 = [3,2,4,1, 1]
list2 = [three, two, four, one, one2]

Если я запустил list1.sort(), он будет сортировать его до [1,1,2,3,4], но есть ли способ сохранить синхронизацию list2 (так что я могу сказать, что элемент 4 принадлежит "три" )? Моя проблема заключается в том, что у меня довольно сложная программа, которая отлично работает со списками, но мне нужно начинать ссылаться на некоторые данные. Я знаю, что это идеальная ситуация для словарей, но я стараюсь избегать словарей в моей обработке, потому что мне нужно сортировать ключевые значения (если я должен использовать словари, которые я знаю, как их использовать).

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

4b9b3361

Ответ 1

Один классический подход к этой проблеме - использовать "украшать, сортировать, дебекорировать" идиому, что особенно просто с использованием встроенной функции zip на основе python:

>>> list1 = [3,2,4,1, 1]
>>> list2 = ['three', 'two', 'four', 'one', 'one2']
>>> list1, list2 = zip(*sorted(zip(list1, list2)))
>>> list1
(1, 1, 2, 3, 4)
>>> list2 
('one', 'one2', 'two', 'three', 'four')

Они, конечно, больше не являются списками, но это легко исправляется, если это имеет значение:

>>> list1, list2 = (list(t) for t in zip(*sorted(zip(list1, list2))))
>>> list1
[1, 1, 2, 3, 4]
>>> list2
['one', 'one2', 'two', 'three', 'four']

Стоит отметить, что вышеизложенное может пожертвовать скоростью для терпения; версия на месте, которая занимает 3 строки, немного медленнее на моей машине для небольших списков:

>>> %timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 3.3 us per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best of 3: 2.84 us per loop

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

>>> %timeit zip(*sorted(zip(list1, list2)))
100 loops, best of 3: 8.09 ms per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100 loops, best of 3: 8.51 ms per loop

Как указывает Quantum7, предложение JSF немного быстрее, но, вероятно, это будет только когда-либо немного быстрее, потому что Python использует та же самая идиома DSU внутри для всех видов на основе ключей. Это просто немного приближается к голым металлам. (Это показывает, насколько хорошо оптимизированы подпрограммы zip!)

Я думаю, что подход на основе zip более гибкий и немного читаем, поэтому я предпочитаю его.

Ответ 2

Вы можете сортировать индексы, используя значения как ключи:

indexes = range(len(list1))
indexes.sort(key=list1.__getitem__)

Получить отсортированные списки с отсортированными индексами:

sorted_list1 = map(list1.__getitem__, indexes)
sorted_list2 = map(list2.__getitem__, indexes)

В вашем случае вы не должны иметь list1, list2, а скорее один список пар:

data = [(3, 'three'), (2, 'two'), (4, 'four'), (1, 'one'), (1, 'one2')]

Легко создать; его легко сортировать в Python:

data.sort() # sort using a pair as a key

Сортировка только по первому значению:

data.sort(key=lambda pair: pair[0])

Ответ 3

Я использовал ответ, полученный senderle в течение длительного времени, пока не обнаружил np.argsort. Вот как это работает.

# idx works on np.array and not lists.
list1 = np.array([3,2,4,1])
list2 = np.array(["three","two","four","one"])
idx   = np.argsort(list1)

list1 = np.array(list1)[idx]
list2 = np.array(list2)[idx]

Я нахожу это решение более интуитивным, и оно работает очень хорошо. Производительность:

def sorting(l1, l2):
    # l1 and l2 has to be numpy arrays
    idx = np.argsort(l1)
    return l1[idx], l2[idx]

# list1 and list2 are np.arrays here...
%timeit sorting(list1, list2)
100000 loops, best of 3: 3.53 us per loop

# This works best when the lists are NOT np.array
%timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 2.41 us per loop

# 0.01us better for np.array (I think this is negligible)
%timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best for 3 loops: 1.96 us per loop

Несмотря на то, что np.argsort не самый быстрый, мне легче его использовать.

Ответ 4

преобразование Шварца. Встроенная сортировка Python стабильна, поэтому два 1 не вызывают проблемы.

>>> l1 = [3, 2, 4, 1, 1]
>>> l2 = ['three', 'two', 'four', 'one', 'second one']
>>> zip(*sorted(zip(l1, l2)))
[(1, 1, 2, 3, 4), ('one', 'second one', 'two', 'three', 'four')]

Ответ 5

Как насчет:

list1 = [3,2,4,1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']

sortedRes = sorted(zip(list1, list2), key=lambda x: x[0]) # use 0 or 1 depending on what you want to sort
>>> [(1, 'one'), (1, 'one2'), (2, 'two'), (3, 'three'), (4, 'four')]

Ответ 6

Одним из способов является отслеживание того, куда идет каждый индекс, путем сортировки идентификаторов [0,1,2,.. n]

Это работает для любого количества списков.

Затем переместите каждый элемент на свою позицию. Использование сростков лучше всего.

list1 = [3,2,4,1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']

index = list(range(len(list1)))
print(index)
'[0, 1, 2, 3, 4]'

index.sort(key = list1.__getitem__)
print(index)
'[3, 4, 1, 0, 2]'

list1[:] = [list1[i] for i in index]
list2[:] = [list2[i] for i in index]

print(list1)
print(list2)
'[1, 1, 2, 3, 4]'
"['one', 'one2', 'two', 'three', 'four']"

Обратите внимание, что мы могли бы перебирать списки, даже не сортируя их:

list1_iter = (list1[i] for i in index)

Ответ 7

Вы можете использовать ключевой аргумент в методе sorted(), если у вас нет двух одинаковых значений в list2.

Код приведен ниже:

sorted(list2, key = lambda x: list1[list2.index(x)]) 

Он сортирует list2 в соответствии с соответствующими значениями в list1, но убедитесь, что при его использовании никакие два значения в list2 не считаются равными, потому что функция list.index() дает первое значение

Ответ 8

Вы можете использовать функции zip() и sort() для выполнения этого:

Python 2.6.5 (r265:79063, Jun 12 2010, 17:07:01)
[GCC 4.3.4 20090804 (release) 1] on cygwin
>>> list1 = [3,2,4,1,1]
>>> list2 = ['three', 'two', 'four', 'one', 'one2']
>>> zipped = zip(list1, list2)
>>> zipped.sort()
>>> slist1 = [i for (i, s) in zipped]
>>> slist1
[1, 1, 2, 3, 4]
>>> slist2 = [s for (i, s) in zipped]
>>> slist2
['one', 'one2', 'two', 'three', 'four']

Надеюсь, что это поможет

Ответ 9

newsource=[];newtarget=[]
for valueT in targetFiles:
    for valueS in sourceFiles:
            l1=len(valueS);l2=len(valueT);
            j=0
            while (j< l1):
                    if (str(valueT) == valueS[j:l1]) :
                            newsource.append(valueS)
                            newtarget.append(valueT)
                    j+=1

Ответ 10

алгоритмическое решение:

list1 = [3,2,4,1, 1]
list2 = ['three', 'two', 'four', 'one', 'one2']


lis = [(list1[i], list2[i]) for i in range(len(list1))]
list1.sort()
list2 = [x[1] for i in range(len(list1)) for x in lis if x[0] == i]

Выходы: -> Скорость выхода: 0.2s

>>>list1
>>>[1, 1, 2, 3, 4]
>>>list2
>>>['one', 'one2', 'two', 'three', 'four']