Или вы можете просто использовать $.each
(который также работает для объектов, а не только для массивов) и построить новый массив следующим образом:
var json = {
'homes': [{
"home_id": "1",
"price": "925",
"sqft": "1100",
"num_of_beds": "2",
"num_of_baths": "2.0",
}, {
"home_id": "2",
"price": "1425",
"sqft": "1900",
"num_of_beds": "4",
"num_of_baths": "2.5",
},
// ... (more homes) ...
{
"home_id": "3-will-be-matched",
"price": "925",
"sqft": "1000",
"num_of_beds": "2",
"num_of_baths": "2.5",
},
]
}
var homes = [];
$.each(json.homes, function(){
if (this.price <= 1000
&& this.sqft >= 500
&& this.num_of_beds >= 2
&& this.num_of_baths >= 2.5
) {
homes.push(this);
}
});
Когда вы пишете [x]*3
, вы получаете, по существу, список [x, x, x]
. То есть список с 3 ссылками на тот же x
. Когда вы затем изменяете этот сингл x
, он отображается через все три ссылки на него.
Чтобы исправить это, вам нужно убедиться, что вы создаете новый список в каждой позиции. Один из способов сделать это -
[[1]*4 for n in range(3)]
, который будет повторно оценивать [1]*4
каждый раз, а не оценивать его один раз и делать 3 ссылки на 1 список.
Вы можете удивиться почему *
не может создавать независимые объекты так, как это делает понимание списка. Это потому, что оператор умножения *
работает с объектами, не видя выражений. Когда вы используете *
для умножения [[1] * 4]
на 3, *
видит только 1-элементный список [[1] * 4]
, а не текст выражения [[1] * 4
. *
не имеет понятия, как делать копии этого элемента, не знаю, как переоценить [[1] * 4]
, и не подозревайте, что вы даже хотите копировать, и вообще, возможно, даже не было способа скопировать элемент.
Единственный вариант *
- это сделать новые ссылки на существующий подсписчик вместо того, чтобы пытаться создавать новые подсписки. Все остальное было бы непоследовательным или требовало бы значительного пересмотра основополагающих решений по языковому дизайну.
Напротив, понимание списка переоценивает выражение элемента на каждой итерации. [[1] * 4 for n in range(3)]
пересчитывает [1] * 4
каждый раз по той же причине [x**2 for x in range(3)]
каждый раз переоценивает x**2
. Каждая оценка [1] * 4
генерирует новый список, поэтому понимание списка делает то, что вы хотели.
Кстати, [1] * 4
также не копирует элементы [1]
, но это не имеет значения , так как целые числа неизменны. Вы не можете сделать что-то вроде 1.value = 2
и превратить 1 в 2.
Попытка объяснить это более описательно,
Операция 1:
x = [[0, 0], [0, 0]]
print(type(x)) # <class 'list'>
print(x) # [[0, 0], [0, 0]]
x[0][0] = 1
print(x) # [[1, 0], [0, 0]]
Операция 2:
y = [[0] * 2] * 2
print(type(y)) # <class 'list'>
print(y) # [[0, 0], [0, 0]]
y[0][0] = 1
print(y) # [[1, 0], [1, 0]]
Заметил, почему не изменяется первый элемент первого списка не изменил второй элемент каждого списка? Это потому, что [0] * 2
действительно представляет собой список из двух чисел, и ссылка на 0 не может быть изменена.
Если вы хотите создать копии клонов, попробуйте выполнить операцию 3:
import copy
y = [0] * 2
print(y) # [0, 0]
y = [y, copy.deepcopy(y)]
print(y) # [[0, 0], [0, 0]]
y[0][0] = 1
print(y) # [[1, 0], [0, 0]]
еще один интересный способ создания копий клонов, операция 4:
import copy
y = [0] * 2
print(y) # [0, 0]
y = [copy.deepcopy(y) for num in range(1,5)]
print(y) # [[0, 0], [0, 0], [0, 0], [0, 0]]
y[0][0] = 5
print(y) # [[5, 0], [0, 0], [0, 0], [0, 0]]
Используя встроенную функцию списка, вы можете сделать это
a
out:[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
#Displaying the list
a.remove(a[0])
out:[[1, 1, 1, 1], [1, 1, 1, 1]]
# Removed the first element of the list in which you want altered number
a.append([5,1,1,1])
out:[[1, 1, 1, 1], [1, 1, 1, 1], [5, 1, 1, 1]]
# append the element in the list but the appended element as you can see is appended in last but you want that in starting
a.reverse()
out:[[5, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
#So at last reverse the whole list to get the desired list
Я думаю, все объясняют, что происходит. Я предлагаю один из способов его решения:
myList = [[1 for i in range(4)] for j in range(3)]
myList[0][0] = 5
print myList
И у вас есть:
[[5, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
Давайте перепишем ваш код следующим образом:
x = 1
y = [x]
z = y * 4
myList = [z] * 3
После этого запустите следующий код, чтобы сделать все более понятным. Что делает код, в основном печатает id
s полученных объектов, которые
Вернуть «идентификатор» объекта
и поможет нам идентифицировать их и проанализировать, что происходит:
print("myList:") for i, subList in enumerate(myList): print("\t[{}]: {}".format(i, id(subList))) for j, elem in enumerate(subList): print("\t\t[{}]: {}".format(j, id(elem)))
И вы получите следующий результат:
x: 1 y: [1] z: [1, 1, 1, 1] myList: [0]: 4300763792 [0]: 4298171528 [1]: 4298171528 [2]: 4298171528 [3]: 4298171528 [1]: 4300763792 [0]: 4298171528 [1]: 4298171528 [2]: 4298171528 [3]: 4298171528 [2]: 4300763792 [0]: 4298171528 [1]: 4298171528 [2]: 4298171528 [3]: 4298171528
Итак, теперь давайте шаг за шагом. У вас есть
x
, который является1
, и единственным списком элементовy
, содержащимx
. Ваш первый шаг -y * 4
, который даст вам новый списокz
, который в основном[x, x, x, x]
, т. Е. Создает новый список, который будет содержать 4 элемента, которые являются ссылками на исходный объектx
. Чистый шаг очень похож. В основном вы делаетеz * 3
, который является[[x, x, x, x]] * 3
и возвращает[[x, x, x, x], [x, x, x, x], [x, x, x, x]]
по той же причине, что и для первого шага.
id
, прежде чем вы бросаете этот код у людей.
– PascalVKooten
10 June 2015 в 14:56
size = 3
matrix_surprise = [[0] * size] * size
matrix = [[0]*size for i in range(size)]
[/g1]
x
. Если вы сделаете глобально уникальный объект с x = object()
, а затем сделаете matrix = [[x] * 2]
, это произойдет как истина: matrix[0][0] is matrix[0][1]
– nadrimajstor
2 July 2017 в 13:13
Собственно, подумайте об этом в другом случае. Предположим, что если ваш список таков:
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
, и если вы напишете myList[0][0] = 5
, вы получите:
>>>
[[5, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
>>>
Как и ожидалось. Но так как вы определяете свою переменную списка следующим образом:
[[1] * 4] * 3
Python обработает ваши коды по этому шаблону. Поэтому, если вы напишете myList[0][0]
и ваш список, как указано выше, Python обработает его, как [1]*3
. Вот почему все списки первых элементов изменены.
myList = [[1]*4] * 3
создает один объект списка [1,1,1,1]
в памяти и копирует его ссылку 3 раза. Это эквивалентно obj = [1,1,1,1]; myList = [obj]*3
. Любая модификация obj
будет отражена в трех местах, где obj
упоминается в списке. Правильным утверждением будет:
myList = [[1]*4 for _ in range(3)]
или
myList = [[1 for __ in range(4)] for _ in range(3)]
. Важно отметить, что *
оператор в основном используется для создания список литералов. Поскольку 1
является литералом, значит, obj =[1]*4
создаст [1,1,1,1]
, где каждый 1
будет атомарным, а не ссылкой 1
, повторяемым 4 раза. Это означает, что если мы obj[2]=42
, то obj
станет [1,1,42,1]
не [42,42,42,42]
, как могут предположить некоторые.
obj[2] = 42
заменяет ссылку на индекс 2
, в отличие от мутирования объекта, на который ссылается этот индекс, что является myList[2][0] = ...
(myList[2]
является списком, и это изменение изменяет ссылка на индекс 0 в этом списке). Конечно, целые числа не изменяются, но множество типов объектов являются i>. И обратите внимание, что обозначение отображения [....]
также является формой литерального синтаксиса! Не путайте сложные (например, списки) и скалярные объекты (например, целые числа), с изменяемыми или неизменяемыми объектами.
– Martijn Pieters♦
25 July 2018 в 15:52
[[1] * 4] * 3
или даже:
[[1, 1, 1, 1]] * 3
Создает список, который ссылается на внутренний [1,1,1,1]
3 раза - не три копии внутреннего списка, поэтому в любое время, когда вы изменяете список (в любом позиция), вы увидите изменение три раза.
Это то же самое, что и в этом примере:
>>> inner = [1,1,1,1]
>>> outer = [inner]*3
>>> outer
[[1, 1, 1, 1], [1, 1, 1, 1], [1, 1, 1, 1]]
>>> inner[0] = 5
>>> outer
[[5, 1, 1, 1], [5, 1, 1, 1], [5, 1, 1, 1]]
, где это, вероятно, немного менее удивительно.
Наряду с принятым ответом, который правильно объяснил проблему, в понимании вашего списка, если вы используете python-2.x, используйте xrange()
, который возвращает более эффективный генератор (range()
в python 3 выполняет ту же работу ) _
вместо переменной throw n
:
[[1]*4 for _ in xrange(3)] # and in python3 [[1]*4 for _ in range(3)]
Кроме того, в качестве более Pythonic способа вы можете использовать itertools.repeat()
для создания объекта итератора повторяющихся элементов:
>>> a=list(repeat(1,4))
[1, 1, 1, 1]
>>> a[0]=5
>>> a
[5, 1, 1, 1]
PS Используя numpy, если вы хотите создать только массив единиц или нулей, вы можете использовать np.ones
и np.zeros
и / или для использования других чисел np.repeat()
:
In [1]: import numpy as np
In [2]:
In [2]: np.ones(4)
Out[2]: array([ 1., 1., 1., 1.])
In [3]: np.ones((4, 2))
Out[3]:
array([[ 1., 1.],
[ 1., 1.],
[ 1., 1.],
[ 1., 1.]])
In [4]: np.zeros((4, 2))
Out[4]:
array([[ 0., 0.],
[ 0., 0.],
[ 0., 0.],
[ 0., 0.]])
In [5]: np.repeat([7], 10)
Out[5]: array([7, 7, 7, 7, 7, 7, 7, 7, 7, 7])
Простыми словами это происходит потому, что в python все работает по ссылке, поэтому, когда вы создаете список списков таким образом, вы в основном получаете такие проблемы.
Чтобы решить вашу проблему, вы можете сделать либо один из них: 1. Используйте документацию numpy array для numpy.empty 2. Добавьте список, когда вы попадаете в список. 3. Вы также можете использовать словарь, если хотите
Собственно, это именно то, чего вы ожидаете. Давайте разложим, что здесь происходит:
Вы пишете
lst = [[1] * 4] * 3
Это эквивалентно:
lst1 = [1]*4
lst = [lst1]*3
Это означает, что lst
- это список с 3 элемента, указывающие на lst1
. Это означает, что две следующие строки эквивалентны:
lst[0][0] = 5
lst1[0] = 5
Поскольку lst[0]
- это только lst1
.
Чтобы получить желаемое поведение, вы можете использовать понимание списка:
lst = [ [1]*4 for n in xrange(3) ]
В этом случае выражение переоценивается для каждого n, что приводит к другому списку.
id(lst[0][0])
и id(lst[1][0])
или даже id(lst[0])
и id(lst[1])
– Sergiy Kolodyazhnyy
17 May 2017 в 07:08
Контейнеры Python содержат ссылки на другие объекты. См. Этот пример:
>>> a = []
>>> b = [a]
>>> b
[[]]
>>> a.append(1)
>>> b
[[1]]
В этом b
есть список, содержащий один элемент, который является ссылкой на список a
. Список a
изменен.
Умножение списка на целое эквивалентно добавлению списка к себе несколько раз (см. операции общей последовательности ). Итак, продолжаем с примера:
>>> c = b + b
>>> c
[[1], [1]]
>>>
>>> a[0] = 2
>>> c
[[2], [2]]
Мы видим, что список c
теперь содержит две ссылки на список a
, который эквивалентен c = b * 2
.
Python FAQ также содержит объяснение этого поведения: Как создать многомерный список?
[x]*3
хранить 3 ссылки, такие как[x, x, x]
, только в том случае, когдаx
изменен. Это не работает, например.a=[4]*3
, где послеa[0]=5
,a=[5,4,4].
– Allanqunzi 22 May 2015 в 00:16[4]*3
по существу эквивалентенx = 4; [x, x, x]
. Правда, это никогда не вызовет проблемы i>, так как4
является неизменным. Кроме того, ваш другой пример - это не совсем другой случай.a = [x]*3; a[0] = 5
не вызовет проблем, даже еслиx
изменен, поскольку вы не изменяетеx
, только изменяяa
. Я бы не описал мой ответ как вводящий в заблуждение или неправильный - вы просто не можете i> стрелять в ногу, если вы имеете дело с неизменяемыми объектами. – CAdaker 22 May 2015 в 08:04x = 1000; lst = [x]*2; lst[0] is lst[1]
- & gt;True
. Python не различает здесь изменяемые и неизменяемые объекты. – timgeb 17 April 2016 в 18:081
в2
, но это не так просто, как1.value = 2
. – Zach Gates 12 September 2017 в 19:35