Python Сортировка списка на основе заданного порядка

У меня есть список, скажем A = [[3,5],[1,3],[6,1]] .

И у меня есть другой список, скажем B = [6,1,3]

Я хочу сортировать список A, чтобы A становился [[6,1],[1,3],[3,5]] , который соответствует данному BIe, первый член каждого подсписца A должен быть отсортирован в соответствии с B.

6 Solutions collect form web for “Python Сортировка списка на основе заданного порядка”

вывести диктовку, отображающую числа в B по их индексам и использовать их в функции сортировки. Таким образом, вы сохраняете ключевую функцию постоянным временем.

 >>> A = [[3,5],[1,3],[6,1]] >>> B = [6,1,3] >>> srt = {b: i for i, b in enumerate(B)} >>> sorted(A, key=lambda x: srt[x[0]]) [[6, 1], [1, 3], [3, 5]] 

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

Также, если есть запись в A, не совпадающая с B, у вас есть KeyError . Вы можете немного смягчить это, используя dict.get с некоторым значением по умолчанию, но если ваши исходные данные были навинчены для начала, ошибка – это хорошая вещь для получения.

Вы можете искать, где каждый [0] элемент A находится с использованием .index в B

 >>> sorted(A, key = lambda i: B.index(i[0])) [[6, 1], [1, 3], [3, 5]] 

или сортировка по месту

 >>> A.sort(key = lambda i: B.index(i[0])) >>> A [[6, 1], [1, 3], [3, 5]] 

Это очень похоже на ответ CoryKramer, но это немного быстрее. Вместо использования функции сортировки вручную вставляйте элементы в другой список. Таким образом, index метод вызывается реже. (Этот код предполагает, что элементы из b различны).

 a= [[3,5],[1,3],[6,1]] b=[6,1,3] c= [-1]*len(b) # dummy data for x in a: c[b.index(x[0])]= x print(c) 

Предполагая, что A и B имеют одинаковую длину, каждый из первых элементов кортежей в A соответствует элементу из B и дубликатов нет, вы можете использовать это:

 >>> A = [[3,5],[1,3],[6,1]] >>> B = [6,1,3] >>> A_ind = {b: [b, a] for (b, a) in A} >>> [A_ind[b] for b in B] [[6, 1], [1, 3], [3, 5]] 

Это просто создает dict , сопоставляя b часть от A ко всем элементам и просматривая соответствующие элементы в B в этом dict . Используя ни sorted index , это имеет сложность O (n).

Если могут быть повторяющиеся элементы, вы можете создать ключи сопоставления dict (или defaultdict ) для списков элементов, имеющих этот ключ:

 >>> A = [[3,5],[1,3],[6,1],[1,4]] >>> A_ind = collections.defaultdict(list) >>> for b, a in A: ... A_ind[b].append([b,a]) ... >>> B = [6,1,3,1] >>> [a for b in B for a in A_ind[b]] [[6, 1], [1, 3], [1, 4], [3, 5], [1, 3], [1, 4]] 

Или переверните list в iter ators, чтобы распределить значения в A с соответствующими ключами в B :

 >>> A_ind = {k: iter(v) for k, v in A_ind.items()} >>> [next(A_ind[b]) for b in B] [[6, 1], [1, 3], [3, 5], [1, 4]] 
 sorted(A, key=lambda x: B.index(x[0])) 

Преобразуйте список пар в dict :

 a_dict = dict(A) 

В зависимости от того, что вы делаете, вы можете сделать это. Например, если вы хотите print каждую пару, вы можете просто сделать это:

 for b in B: print([b, a_dict[b]]) 

Если вам действительно нужен фактический список в конце, просто перейдите по B чтобы построить его непосредственно в понимании:

 result = [[b, a_dict[b]] for b in B] 

(Замените result на A если вы хотите отменить исходный список.)

Здесь нет необходимости вызывать sort или sorted явно, так как B уже в желаемом порядке. Это решение просто использует существующий порядок B

Я не знаю, является ли это самым быстрым решением для одной пары, но если вам нужно сортировать один и тот же A несколько раз по различным заказам, я подозреваю, что он победит над другими, поскольку доступ к a_dict является постоянным временем и итерацией по B является линейным. Даже если это не самый быстрый, это, на мой взгляд, самый простой . Не микро-оптимизируйте, если вы не уверены, что это решение создает узкое место.

Предположения

  • KeyError в порядке, если B содержит значение, отсутствующее в первом элементе в элементах A (В этом решении, если нужно, просто обращаться с этим по-другому. Например, просто измените a_dict[b] на a_dict.get(b, 50) если вы хотите, например, значение по умолчанию 50 Или вы можете добавить if b in a_dict.keys() для понимания, если вы хотите просто пропустить их.)
  • Дополнительные служебные данные памяти являются допустимыми.
  • Если B не содержит всех ключей в a_dict , это не проблема. ( a_dict.keys() здесь не так сложно. Вы просто проверяете, a_dict.keys() ли a_dict.keys() и B все те же элементы, возможно, путем преобразования в множества и сравнения для равенства.)
  • У вас фактически нет более длинного списка для каждого элемента. (Опять же, если вы это сделаете, исправление просто. Просто a_dict = {a[0]: a for a in A} его следующим образом: a_dict = {a[0]: a for a in A} и замените все экземпляры [b, a_dict[b]] только a_dict[b] .)
  • У вас нет дубликатов первых элементов.

Надеюсь, легкость модификации во всех допущениях дает понять, почему простота здесь очень приятная.

  • Python: печать списка без скобок и одинарных кавычек?
  • Самый быстрый способ подсчета числа вхождений в списке Python
  • Как передать элементы кортежей функции в качестве аргументов в python?
  • Python - значения номера заказа в списке, содержащем строки и номера
  • Преобразование списка чисел в строки
  • Сортировка списка словарей несколькими клавишами с различным порядком
  • Сравнение двух списков в Python
  • как получить все ключи и значения во вложенном dict-of-dicts и dicts?
  •  
    Interesting Posts for Van-Lav
    Python - лучший язык программирования в мире.