Удалить элемент с циклом for в файле geojson

для лямбда-файла .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()

Эти решения не работают, почему? Большое спасибо.

Они не работают, потому что синтаксис кода неверен из-за непарных кавычек.

mkrieger1 22.12.2020 01:30

Я отредактировал, очевидно, моя проблема осталась прежней.

Tim 22.12.2020 01:33

Кажется, я не понимаю. в чем именно проблема?: Вы сказали, что это не работает, не могли бы вы рассказать об этом подробнее? Что не так с data['features'].remove(k)?

codewelldev 22.12.2020 01:42

С del k мой файл точно такой же на выходе, а с data['features'].remove(k) удаляется только часть структур, у которых есть ключ label... Я пробовал с файлом, у которого есть только две структуры, обе из которых имеют ключ label, только первая это удалить (фактически первый k).

Tim 22.12.2020 01:52

Да print('ok') работает.

Tim 22.12.2020 01:55

Я обычно использую операторы print() для отладки любого кода, с которым я работаю, пробовали ли вы print(data) просто посмотреть, как выглядит словарь, чтобы убедиться, что формат согласован?

codewelldev 22.12.2020 02:01

Мне трудно воссоздать эту проблему. Для меня data["features"].remove(k) удаляет все структуры с ключом 'label'.

codewelldev 22.12.2020 02:09

Да, пробовала print(data), вроде неплохо. Я даже пробовал со стандартным файлом .geojson, например здесь, добавляя в каждый properties ключ label, это не работает.

Tim 22.12.2020 02:31
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
8
606
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Рассмотрим этот пример:

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 не работает... знаете?

Tim 22.12.2020 13:57

@ Тим, я только что добавил к своему ответу пояснение к утверждению del в вашей ситуации.

codewelldev 22.12.2020 23:14

Другие вопросы по теме