для лямбда-файла .geojson:
{ "type": "FeatureCollection",
"features": [
{ "type": "Feature",
"geometry": {
"type": "Point",
"coordinates": [102.0, 0.5]
},
"properties": {
"label": "value0",
...
}
},
{ "type": "Feature",
"geometry": {..
Я хотел бы удалить структуры типа «Точка», «Многоугольник» и даже «Мультиполигон», у которых есть ключ 'label'
в properties
.
import json
file = open('file.geojson', 'r')
data = json.load(file)
for k in data['features']:
if 'label' in k['properties']:
print('ok') #displays the right number of structure, so the loop works
del k #doesn't work
#data['features'].remove(k) works but delete only a part of elements in the file..
print('okk') #displays so del doesn't work
data_srt = open('file.geojson', 'w')
data_srt.write(json.dumps(data, ensure_ascii=False, indent=2))
data_srt.close()
Эти решения не работают, почему? Большое спасибо.
Я отредактировал, очевидно, моя проблема осталась прежней.
Кажется, я не понимаю. в чем именно проблема?: Вы сказали, что это не работает, не могли бы вы рассказать об этом подробнее? Что не так с data['features'].remove(k)
?
С del k
мой файл точно такой же на выходе, а с data['features'].remove(k)
удаляется только часть структур, у которых есть ключ label
... Я пробовал с файлом, у которого есть только две структуры, обе из которых имеют ключ label
, только первая это удалить (фактически первый k).
Да print('ok')
работает.
Я обычно использую операторы print()
для отладки любого кода, с которым я работаю, пробовали ли вы print(data)
просто посмотреть, как выглядит словарь, чтобы убедиться, что формат согласован?
Мне трудно воссоздать эту проблему. Для меня data["features"].remove(k)
удаляет все структуры с ключом 'label'
.
Да, пробовала print(data)
, вроде неплохо. Я даже пробовал со стандартным файлом .geojson, например здесь, добавляя в каждый properties
ключ label
, это не работает.
Рассмотрим этот пример:
l = [1, 2, 3]
for i in l:
l.remove(i)
print(l) # Prints '[2]'
Во время первой итерации i == l[0]
. l.remove(i)
будет таким же, как l.remove(l[0])
. Во время второй итерации i == l[1]
. На данный момент, однако, l == [2, 3]
, потому что l[0]
был удален. Итак, во второй итерации l.remove(i)
совпадает с l.remove(l[1])
. После того, как это будет выполнено, l == [2]
. Если цикл пытается продолжиться до третьей итерации, i == l[2]
. Однако теперь, когда l == [2]
, len(l) == 1
так что l[2]
выходит за рамки. Из-за этого цикл for
останавливается, хотя l
не пуст. По сути, это та же проблема, с которой вы столкнулись.
Чтобы исправить это:
i = len(l) - 1
while i >= 0:
l.remove(l[i])
i -= 1
Повторение списка в обратном порядке позволяет избежать проблемы выхода за границы, с которой мы сталкивались ранее.
Чтобы применить эту концепцию в вашей ситуации, это решение:
i = len(data["features"]) - 1
while i >= 0:
if "label" in data["features"][i]["properties"]:
data["features"].pop(i)
i -= 1
Я только что придумал новое, лучшее решение (оно использует функцию reversed()
):
for k in reversed(data["features"]):
if "label" in k["properties"]:
data["features"].remove(k)
Здесь используется та же концепция обратной итерации, но функция reversed()
позаботится об этом за вас.
Причина, по которой оператор del
не имел для вас функциональности, вызвана более сложной концепцией. Я сделаю все возможное, чтобы объяснить (вот еще один ответ, который помогает объяснить это: https://stackoverflow.com/a/14814847/13911868).
При переборе списка или любого контейнера в цикле for
, например:
l = [1, 2, 3]
for i in l:
del i
Переменная i
— это глубокая копия элемента в l
, а не ссылка. В этом случае del i
удалит только скопированный элемент, а не исходный элемент из l
.
С другой стороны, в этом примере:
l = [1, 2, 3]
for i in range(len(l)):
del l[i]
del l[i]
удалит исходный элемент в l
, потому что l[i]
возвращает этот исходный объект, а не копию.
Однако в этом примере вы столкнетесь с той же проблемой выхода за пределы, что и раньше, поэтому рабочим решением с использованием оператора del
будет:
for k in reversed(range(len(data["features"]))):
if "label" in data["features"][k]["properties"]:
del data["features"][k]
Большое спасибо за ваши объяснения! И я до сих пор не понимаю, почему del
не работает... знаете?
@ Тим, я только что добавил к своему ответу пояснение к утверждению del
в вашей ситуации.
Они не работают, потому что синтаксис кода неверен из-за непарных кавычек.