как вычесть две строки в python [duplicate]

: P Ты спускаешься в мельчайшие детали, и я рад, что ты спросил, как ты будешь мудрее к концу.

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

Давайте начнем с ввода первых нескольких строк вашего кода:

var a, b;

a = {}
b = a;

Вы сделали здесь один объект в куче и два символа в таблице символов. Это выглядит примерно так:


Таблица символов :

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|      a |        0x400000 |
+--------+-----------------+
|      b |        0x400000 |
+--------+-----------------+

Куча :

+----------+-----------------+
| Location | Value           |
+----------+-----------------+
| 0x400000 | <object val 1>  |
+----------+-----------------+

.


Здесь интересны вещи: у объектов есть свои «таблички символов» (обычно это просто хеш-таблицы, но называть их таблицей символов можно сделать более ясным).

Теперь, после вашего следующего утверждения, у вас есть 3 вещи: таблица глобального символа, таблица символов <object val 1> и куча.

Запустите следующую строку:

a['one'] = {}

И теперь все выглядит так:


Глобальная таблица символов :

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|      a |        0x400000 |
+--------+-----------------+
|      b |        0x400000 |
+--------+-----------------+

<object val 1> Таблица символов

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|    one |        0x400004 |
+--------+-----------------+

Куча :

+----------+-----------------+
| Location | Value           |
+----------+-----------------+
| 0x400000 | <object val 1>  |
+----------+-----------------+
| 0x400004 | <object val 2>  |     <---we created a new object on the heap
+----------+-----------------+

.


Теперь вы выполнили следующий код:

a = a['one'];

Это, должно быть, кажется тривиальным изменением. Результат:


Таблица глобальных символов :

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|      a |        0x400004 |
+--------+-----------------+
|      b |        0x400000 |
+--------+-----------------+

Символьная таблица <object val 1>

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|    one |        0x400004 |
+--------+-----------------+

Куча :

+----------+-----------------+
| Location | Value           |
+----------+-----------------+
| 0x400000 | <object val 1>  |
+----------+-----------------+
| 0x400004 | <object val 2>  | 
+----------+-----------------+

.


Следуя ячейкам памяти в куче, мы, надеюсь, сделаем это ясно, почему вы получили результат, который вы сделали.

Теперь все становится еще интереснее, потому что теперь вы делаете:

a['two'] = 2;

Хорошо, давайте сделаем это шаг за шагом.

  • a указывает на ячейку памяти 0x400004, которая содержит <object val 2>
  • <object val 2> - пустой объект, поэтому его таблица символов начинает пуст
  • Запустив эту строку, мы добавим переменную «two» в таблицу символов <object val 2>.

Если вы еще не устали смотреть на эти диаграммы, вы будете быть. Теперь все выглядит так:


Таблица глобальных символов :

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|      a |        0x400004 |
+--------+-----------------+
|      b |        0x400000 |
+--------+-----------------+

Символьная таблица <object val 1>

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|    one |        0x400004 |
+--------+-----------------+

<object val 2> Символьная таблица

+--------+-----------------+
| Symbol | Memory Location |
+--------+-----------------+
|    two |        0x400008 |
+--------+-----------------+

Куча :

+----------+-----------------+
| Location | Value           |
+----------+-----------------+
| 0x400000 | <object val 1>  |
+----------+-----------------+
| 0x400004 | <object val 2>  | 
+----------+-----------------+
| 0x400008 | 2 (literal val) |    <-- yes, even integers are stored on the heap
+----------+-----------------+        in JavaScript.

.


Если вы усердно занимаете время, чтобы следить за местоположениями памяти, вы увидите, что ваш браузер отобразил правильный вывод.

157
задан Marvin Cohen 21 March 2018 в 16:36
поделиться

12 ответов

Используйте map с operator.add :

>>> from operator import add
>>> list( map(add, list1, list2) )
[5, 7, 9]

или zip со списком понимание:

>>> [sum(x) for x in zip(list1, list2)]
[5, 7, 9]

Сроки сравнения:

>>> list2 = [4, 5, 6]*10**5
>>> list1 = [1, 2, 3]*10**5
>>> %timeit from operator import add;map(add, list1, list2)
10 loops, best of 3: 44.6 ms per loop
>>> %timeit from itertools import izip; [a + b for a, b in izip(list1, list2)]
10 loops, best of 3: 71 ms per loop
>>> %timeit [a + b for a, b in zip(list1, list2)]
10 loops, best of 3: 112 ms per loop
>>> %timeit from itertools import izip;[sum(x) for x in izip(list1, list2)]
1 loops, best of 3: 139 ms per loop
>>> %timeit [sum(x) for x in zip(list1, list2)]
1 loops, best of 3: 177 ms per loop
249
ответ дан Utku 16 August 2018 в 03:33
поделиться
  • 1
    Если вы используете эти огромные массивы, решение numpy от @BasSwinckels - это то, над чем вы должны смотреть. – Henry Gomersall 10 September 2013 в 09:34
  • 2
    Какую версию Python вы использовали для этих таймингов? – arshajii 16 September 2013 в 01:20
  • 3
    @arshajii Это оболочка IPython . – Ashwini Chaudhary 16 September 2013 в 06:47
  • 4
    Нотабене - в python3 map () возвращает итерируемую вещь, а не список. Если вам нужен фактический список, первым ответом будет список (map (add, list1, list2)) – FLHerne 24 March 2016 в 12:25
  • 5
    Отмечая, что проблема python3, отмеченная @FLHerne с map, будет становиться все более важной с течением времени. Python 2 потеряет официальную поддержку менее чем за 3 года. – nealmcb 10 April 2017 в 00:29

Другие приводили примеры того, как это сделать в чистом питоне. Если вы хотите сделать это с помощью массивов с 100 000 элементами, вы должны использовать numpy:

In [1]: import numpy as np
In [2]: vector1 = np.array([1, 2, 3])
In [3]: vector2 = np.array([4, 5, 6])

Выполнение элементарного добавления теперь так же тривиально, как

In [4]: sum_vector = vector1 + vector2
In [5]: print sum_vector
[5 7 9]

так же, как в Matlab.

Сроки сравнения с самой быстрой версией Ashwini:

In [16]: from operator import add
In [17]: n = 10**5
In [18]: vector2 = np.tile([4,5,6], n)
In [19]: vector1 = np.tile([1,2,3], n)
In [20]: list1 = [1,2,3]*n
In [21]: list2 = [4,5,6]*n
In [22]: timeit map(add, list1, list2)
10 loops, best of 3: 26.9 ms per loop

In [23]: timeit vector1 + vector2
1000 loops, best of 3: 1.06 ms per loop

Итак, это на 25 раз быстрее! Но используйте то, что подходит вашей ситуации. Для простой программы вы, вероятно, не хотите устанавливать numpy, поэтому используйте стандартный python (и я нахожу версию Henry самой питонической). Если вы находитесь в серьезном количестве хрустов, пусть numpy делает тяжелый подъем. Для скорости freaks: кажется, что решение numpy быстрее начинается с n = 8.

77
ответ дан Bas Swinckels 16 August 2018 в 03:33
поделиться

Если вам нужно обрабатывать списки разных размеров, не беспокойтесь! Замечательный модуль itertools вы рассмотрели:

>>> from itertools import zip_longest
>>> list1 = [1,2,1]
>>> list2 = [2,1,2,3]
>>> [sum(x) for x in zip_longest(list1, list2, fillvalue=0)]
[3, 3, 3, 3]
>>>

В Python 2 zip_longest называется izip_longest .

См. также этот ответ и комментарий к другому вопросу .

1
ответ дан Community 16 August 2018 в 03:33
поделиться

Это просто с numpy.add()

import numpy

list1 = numpy.array([1, 2, 3])
list2 = numpy.array([4, 5, 6])
result = numpy.add(list1, list2) # result receive element-wise addition of list1 and list2
print(result)
array([5, 7, 9])

См. здесь doc

Если вы хотите получить список python:

result.tolist()
1
ответ дан Eduardo Basílio 16 August 2018 в 03:33
поделиться

Хотя, фактический вопрос не хочет перебирать список для генерации результата, но все предлагаемые решения делают именно то, что находится под капотом!

Чтобы обновить: вы не можете добавить два вектора, не просматривая все векторные элементы. Таким образом, алгоритмическая сложность большинства этих решений - Big-O (n). Где n - размерность вектора.

Итак, с алгоритмической точки зрения использование цикла for для итеративного генерации результирующего списка является логическим и питоновым. Однако, кроме того, этот метод не имеет накладных расходов на вызов или импорт какой-либо дополнительной библиотеки.

# Assumption: The lists are of equal length.
resultList = [list1[i] + list2[i] for i in range(len(list1))]

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

0
ответ дан Ehsan 16 August 2018 в 03:33
поделиться

Возможно, «самый пифонический путь» должен включать обработку случая, когда list1 и list2 не имеют одинакового размера. Применение некоторых из этих методов позволит вам дать ответ. Метод numpy даст вам знать, скорее всего, с помощью ValueError.

Пример:

import numpy as np
>>> list1 = [ 1, 2 ]
>>> list2 = [ 1, 2, 3]
>>> list3 = [ 1 ]
>>> [a + b for a, b in zip(list1, list2)]
[2, 4]
>>> [a + b for a, b in zip(list1, list3)]
[2]
>>> a = np.array (list1)
>>> b = np.array (list2)
>>> a+b
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: operands could not be broadcast together with shapes (2) (3)

Какой результат вы хотите, если бы это было в функции в вашей проблеме?

4
ответ дан Fred Mitchell 16 August 2018 в 03:33
поделиться
[a + b for a, b in zip(list1, list2)]
49
ответ дан Henry Gomersall 16 August 2018 в 03:33
поделиться
  • 1
    @deltab Принимаемый ответ быстрее И он содержит этот ответ (более информативный) – Sibbs Gambling 11 September 2013 в 11:02
  • 2
    @ perfectionm1ng, хотя я понимаю вашу точку зрения (и не жалею об этом один бит). Я просто подумал, что стоит указать, что я всегда буду использовать либо решение, которое я представил (которое, учитывая его, не требует импорта, возможно, является самым простым, а также как возможно более питоновское), или где скорость подсчитывается, ответ Bas Swinckel , который в подавляющем большинстве является правильным вариантом, когда скорость имеет значение. – Henry Gomersall 11 September 2013 в 11:41
  • 3
    Да. Спасибо за мнение. Но, по существу, [sum(x) for x in zip(list1, list2)] совпадает с вашим ответом, не так ли? :) – Sibbs Gambling 11 September 2013 в 11:55
  • 4
    @ perfectionm1ng Более или менее (хотя он был добавлен после моего редактирования :). Лично я предпочитаю нотацию a + b с явной распаковкой кортежа для удобочитаемости и pythonicness. – Henry Gomersall 11 September 2013 в 12:01

Я не приурочил его, но я подозреваю, что это будет довольно быстро:

import numpy as np
list1=[1, 2, 3]
list2=[4, 5, 6]

list_sum = (np.add(list1, list2)).tolist()

[5, 7, 9]
3
ответ дан litepresence 16 August 2018 в 03:33
поделиться

По моему мнению, проще использовать numpy:

import numpy as np
list1=[1,2,3]
list2=[4,5,6]
np.add(list1,list2)

Результаты:

Подробный параметр информацию, проверьте здесь: numpy.add

2
ответ дан Ludwig Zhou 16 August 2018 в 03:33
поделиться

Как описано другими, быстрое, а также эффективное решение пространства использует numpy (np) с его встроенной возможностью векторной манипуляции:

1. С Numpy

x = np.array([1,2,3])
y = np.array([2,3,4])
print x+y

2. С встроенными функциями

2.1 Lambda

list1=[1, 2, 3]
list2=[4, 5, 6]
print map(lambda x,y:x+y, list1, list2)

Обратите внимание, что map () поддерживает несколько аргументов.

2.2 zip и понимание списка

list1=[1, 2, 3]
list2=[4, 5, 6]
print [x + y for x, y in zip(list1, list2)]
6
ответ дан MYGz 16 August 2018 в 03:33
поделиться

Использовать карту с лямбда-функцией:

>>> map(lambda x, y: x + y, list1, list2)
[5, 7, 9]
2
ответ дан Peaters 16 August 2018 в 03:33
поделиться
[list1[i] + list2[i] for i in range(len(list1))]
1
ответ дан rayryeng 16 August 2018 в 03:33
поделиться
  • 1
    Больше pythonic будет [a + b for (a, b) in zip(list1, list2)] – rayryeng 30 May 2017 в 20:50
Другие вопросы по тегам:

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