Python - копирование индекса отсортированного списка [duplicate]

Быстрое исправление:

Чтобы удалить зазор под изображением, вы можете:

  • Установить свойство vertical-align изображения на vertical-align: bottom; vertical-align: top; или vertical-align: middle;
  • Установите для свойства отображения изображения значение display:block;

См. следующий код для живой демонстрации:

#vAlign img {
  vertical-align :bottom;
}
#block img{
  display:block;
}

div {border: 1px solid red;width:100px;}
img {width:100px;}

No fix:

With vertical-align:bottom; on image:

With display:block; on image:


Объяснение: почему существует пробел под изображением?

Разрыв или дополнительное пространство под изображением не является ошибкой или проблемой, это поведение по умолчанию. Основная причина заключается в том, что изображения заменяются элементами ( см. MDN и W3C ). Это позволяет им «действовать как изображение» и иметь собственные собственные размеры, соотношение сторон ... Браузеры вычисляют свое свойство отображения inline, но они придают им особое поведение, которое приближает их к элементам inline-block (так как вы

Это также означает, что:

[...] когда изображения используются во встроенном контексте форматирования с выравниванием по вертикали: базовая линия, нижняя часть изображения будет отображаться на базовой линии контейнера. ( source: MDN , focus mine )

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

Location of the baseline on text [/g15]

Элементы, выровненные по базовой линии, должны содержать место для дескрипторов которые простираются ниже базовой линии (например, j, p, g ...), как вы можете видеть на приведенном выше изображении. В этой конфигурации нижняя часть изображения выравнивается по базовой линии, как вы можете видеть в этом примере:

div{border:1px solid red;}
img{width:100px;height:auto;}
jpq are letters with descender

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

div {width: 100px;border: 1px solid red;}
img {width: 100px;height: auto;}

.block img{
  display:block;
}
.bottom img{
  vertical-align:bottom;
}

Default:

With display:block;

With vertical-align:bottom;

80
задан Error_404 19 March 2012 в 04:43
поделиться

8 ответов

Один классический подход к этой проблеме - использовать «украшать, сортировать, дебекорировать» идиому, что особенно просто с использованием встроенной функции 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!) [/ ​​G6]

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

140
ответ дан Community 19 August 2018 в 15:05
поделиться
  • 1
    что представляет собой звездочка в третьей строке? – Jeffrey 19 March 2012 в 07:25
  • 2
    @Jeffrey: это splat – georg 19 March 2012 в 10:48
  • 3
    Чтобы подробнее остановиться на этом, оператор * делает распаковку аргументов , – senderle 19 March 2012 в 17:46
  • 4
    Сортированная парадигма индекса / карты, предложенная Я. Ф. Себастьяном, примерно на 10% быстрее, чем решение для zip для меня (с использованием списков 10000 случайных чисел):% timeit index = range (len (l1)); index.sort (ключ = l1 .__ getitem__); map (l1 .__ getitem__, index); map (l2 .__ getitem__, index) 100 циклов, лучше всего 3: 8,04 мс за цикл (против 9,17 мс, 9,07 мс для таймингов senderle) – Quantum7 12 August 2013 в 22:35
  • 5
    Первый и второй zip в списке1, list2 = zip (* sorted (zip (list1, list2))) делают разные вещи. * Все имеет значение. – ashu 13 January 2018 в 10:48

Как насчет:

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')]
3
ответ дан Artsiom Rudzenka 19 August 2018 в 15:05
поделиться

Я использовал ответ, полученный 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 не самый быстрый, я считаю его более удобным.

8
ответ дан Daniel Thaagaard Andreasen 19 August 2018 в 15:05
поделиться
  • 1
    Я получаю сообщение об ошибке с вашим примером: TypeError: only integer arrays with one element can be converted to an index (Python 2.7.6, numpy 1.8.2). Чтобы исправить это, list1 и list2 должны быть объявлены как массивы numpy. – BenB 7 July 2015 в 00:53
  • 2
    Благодарю. Разве это не то, что я пишу в комментарии в функции? Во всяком случае, я думаю, что это глупо, что np.argsort не пытаются преобразовать в np.array внутренне. – Daniel Thaagaard Andreasen 7 July 2015 в 12:37
  • 3
    Я имел в виду первый фрагмент кода, так как он не запускается как написанный :) – BenB 7 July 2015 в 20:50
  • 4
    Я скорректировал его, преобразовывая списки, когда они назначены массивам numpy. Спасибо за комментарий :) – Daniel Thaagaard Andreasen 8 July 2015 в 14:47
  • 5
    Теперь они дважды преобразуются в массивы Numpy;) – BenB 8 July 2015 в 19:32

Вы можете использовать функции 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']

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

1
ответ дан Hunter McMillen 19 August 2018 в 15:05
поделиться

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

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])
19
ответ дан jfs 19 August 2018 в 15:05
поделиться
  • 1
    Самое интересное в том, что я могу продолжать индексировать и сортировать другие вещи позже, в случае, если list1 является важной координатой, которая затрагивает несколько других массивов. – EL_DON 5 March 2018 в 19:35

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

>>> 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')]
10
ответ дан Karl Knechtel 19 August 2018 в 15:05
поделиться
  • 1
    Однако, если вы обнаружите, что вам нужно это сделать, вы должны серьезно подумать о наличии двух «параллельных», списки данных, в отличие от хранения списка из 2-х кортежей (пар) ... или, возможно, даже создания класса. – Karl Knechtel 19 March 2012 в 04:47

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

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

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

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

index = 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)
2
ответ дан robert king 19 August 2018 в 15:05
поделиться

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

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

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

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

0
ответ дан Saurav Yadav 19 August 2018 в 15:05
поделиться
Другие вопросы по тегам:

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