Как отсортировать атрибуты объекта - PullRequest
2 голосов
/ 26 февраля 2012

У меня есть объект примерно так:

class Hand(object):
    def __init__(self, finger_names, finger_lengths, nail_sizes):
        self.finger_names = finger_names
        self.finger_lengths = finger_lengths
        self.nail_sizes = nail_sizes

   def _sort_by_finger_lengths(self):
        ????

finger_names, finger_lengths и nail_sizes являются либо одинаково длинными списками, либо пустыми (например, если человек еще не измерил свои nail_sizes). Цель состоит в том, чтобы отсортировать атрибуты объекта по finger_lengths. Поэтому, если вы начнете с объекта Hand, где списки упорядочены по именам слева направо (мизинец, кольцо, середина, указатель, большой палец), вы получите объект Hand со всеми атрибутами, отсортированными по finger_lengths.

Вот так:

finger_names = [pinky, thumb, pointer, ring, middle]
finger_lengths = [6, 7, 12, 13, 15]
nail_sizes = []

РЕДАКТИРОВАНИЕ ДОБАВИТЬ : Рука - это просто пример класса. Реальный код имеет веские причины для наличия списков для каждого атрибута.

Ответы [ 3 ]

3 голосов
/ 26 февраля 2012

Любое количество людей может сказать вам, как это сделать, но это кажется хрупким.Почему бы не создать класс Finger и сэкономить себе здравомыслие?

class Finger(object):
  PINKY = 0
  RING = 1
  MIDDLE = 2
  INDEX = 3
  THUMB = 4

  def __init__ (self, type):
    self.type = type
    self.length = None
    self.nail_size = None

  def __lt__ (self, other):
    return self.length < other.length

f = Finger(Finger.PINKY)
f.length = 6

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

0 голосов
/ 26 февраля 2012

Вы можете использовать один список с кортежами всех трех атрибутов, чтобы сохранять их вместе во время сортировки.Простой способ сделать это с помощью кода сортировки с использованием существующих структур данных - использовать zip для объединения и распаковки их следующим образом:

l = zip(finger_lengths, finger_names, nail_sizes)
l.sort()
finger_lengths, finger_names, nail_sizes = zip(*l)

Это не сработает, если ваши размеры ногтей пустыетак что даже если нет ничего, вы должны заполнить его нулями, например nail_sizes = [0] * 5.Если вы хотите сохранить структуры данных в виде отдельных списков, я предлагаю сделать это следующим образом.В противном случае, если вы не возражаете реорганизовать его, чтобы он был более объектно-ориентированным, может быть, лучше сделать, как говорит Ник, и создать класс пальца.

0 голосов
/ 26 февраля 2012

Один простой подход заключается в следующем:

>>> finger_names, finger_lengths
(('pointer', 'ring', 'pinky', 'middle', 'thumb'), (12, 13, 6, 15, 7))
>>> s_tuples = sorted(zip(finger_names, finger_lengths), key=lambda x: x[1])
>>> finger_names, finger_lengths = zip(*s_tuples)
>>> finger_names, finger_lengths
(('pinky', 'thumb', 'pointer', 'ring', 'middle'), (6, 7, 12, 13, 15))

Однако, Ник прав, что вам, вероятно, следует связать их в структуре данных, а не в зависимости от их порядка связывать их.

Вышеприведенная стратегия (с использованием key) все еще работает в этом случае, но вам не нужно использовать zip(*s_tuples), чтобы разъединить их.

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

finger_lengths, finger_names = zip(*sorted(zip(finger_lengths, finger_names)))

Или, если вы хотите выполнить сортировку на месте, сохраняя одну операцию копирования:

s_tuples = zip(finger_lengths, finger_names)
s_tuples.sort()
finger_lengths, finger_names = zip(*temp)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...