kolumbou
@kolumbou
python, html, c#

Как лучше всего организовать сортировку по нескольким параметрам?

Доброго времени суток.

Суть цели:
Есть две переменные, допустим cat и dog, каждая из которых хранит в себе по одному значению float, а так же третья переменная text содержащая некий текст относящийся только к этим двум переменным.
cat = 30.0
dog = 1.0
text = 'description'


Каждый раз по прохождению цикла значения во всех трех переменных меняются.
Нужно их складировать в чем-то по типу словаря (cat:dog) и после чего провести сортировку по cat и dog одновременно.
Принцип сортировки следующий - одновременно cat должно быть начиная с самого меньшего и dog от самого большего - и вывести результат, включающий в себя еще и ту самую переменную text, привязанную к этим двум значениям.

Были идеи сделать с тем же словарем - но я понятия не имею как отсортировать с сохранением отношений cat и dog к переменной text (да и вообще как к ним привязать text).

Пример нужного результата (не включающий text, так как я не знаю как ее сюда присоединить):
dic = {}
cat = 993.0
dog = 4.0
dic.update({cat:dog})
> {993.0: 4.0}
cat = 467.0
dog = 915.0
dic.update({cat:dog})
> {993.0: 4.0, 467.0:915.0}
.... # и еще так раз n
> {993.0: 4.0, 467.0:915.0, 81.0:457.0, 8148.0:119.0, 550.0:43.0, 130.0:91.0}
# после чего сортируем и нужно одновременно получить cat по возрастанию, dog по убыванию:
> {81.0:457.0, 130.0:91.0, 467.0:915.0, 550.0:43.0, 993.0:4.0, 8148.0:119.0}


Вопрос: Как получить отсортированный словарь (а может что-то будет лучше словаря) по cat и dog (как в примере выше) + text?

Буду бесконечно благодарен за любые советы.
  • Вопрос задан
  • 719 просмотров
Решения вопроса 1
@iSergios
Python-разработчик
Очень нетривиально Вы задумали с сортировкой. К слову словарь сортировку не поддерживает, поэтому я бы от него отказался (особенно с учетом того, что у Вас не пара переменных, а три).

Для организации доступа к Вашим трем переменным никаких классов писать не надо, достаточно использовать namedtuple:
>>> import collections
>>> pair = collections.namedtuple('pair',['cat','dog','text'])

Хранить "пары" лучше в списке:
>>> vlist=[]
>>> vlist.append(pair(900,2,'foo'))
>>> vlist.append(pair(500,4,'bar'))
>>> vlist.append(pair(300, 10, 'foobar'))
>>> vlist
[pair(cat=900, dog=2, text='foo'), pair(cat=500, dog=4, text='bar'), pair(cat=300, dog=10, text='foobar')]

При этом будет поддерживаться сортировка по первому параметру (cat):
>>> vlist.sort()
>>> vlist
[pair(cat=300, dog=10, text='foobar'), pair(cat=500, dog=4, text='bar'), pair(cat=900, dog=2, text='foo')]


Заметьте, что на выходе мы будем иметь изменяемый список, что позволит Вам пересортировать его циклом так, как Вам заблагорассудится (скажем, если значения cat у соседних элементов равны, отсортировать их в обратном порядке по значению dog (я правильно понял, что Вы хотели именно это?)).
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
Принцип сортировки следующий - одновременно cat должно быть начиная с самого меньшего и dog от самого большего

В общем случае это невозможно. Вот как по вашему отсортировать {1, 1} и {2, 2}?

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

Создайте класс с 3 полями, реализуйте для него оператор сравнения, в котором укажите необходимое вам отношение порядка (как уже выше я говорил, то, что вы предлагаете реализовать невозможно), кладите объекты в список и сортируйте стандартным sort.
Ответ написан
Комментировать
AtomKrieg
@AtomKrieg
Давай я поищу в Google за тебя
Отделять текст от чисел не очень хорошая идея. Если только не хранить их в отдельном словаре
def compare(x, y):
	if x[0] < y[0]:
		return -1
	elif x[0] > y[0]:
		return 1
	else:
		if x[1] > y[1]: #знаки инвертируются, надо сортировать по 2ой переменной в обратном порядке
			return -1
		elif x[1] < y[1]:
			return 1
		else:
			return 0

subjects = {(30.0,1.0,'description'), ...}

sortedDict = sorted(subjects, cmp=compare)


Ну еще стоит учесть что числа с плавающей запятой сравнивают с использованием eps. Типа x < y+eps, x > y-eps
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы