在 geojson 文件中删除带有 for 循环的元素

delete an element with a for loop in a geojson file

对于 .geojson lambda 文件:

{ "type": "FeatureCollection",
    "features": [
      { "type": "Feature",
        "geometry": {
          "type": "Point",
          "coordinates": [102.0, 0.5]
          },
          "properties": {
            "label": "value0",
             ...
          }
        },
       { "type": "Feature",
         "geometry": {..

我想删除“Point”和“Polygon”甚至“MultiPolygon”类型的结构,它们在 properties 中有一个键 'label'

   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()

这些解决方案不起作用,为什么?非常感谢。

考虑这个例子:

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 语句对您不起作用的原因是由一个更复杂的概念引起的。我会尽力解释(这是另一个有助于解释它的答案:)。

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] returns 原始 对象,不是副本

不过,在此示例中,您会遇到与以前相同的越界问题,因此使用 del 语句的有效 解决方案是:

for k in reversed(range(len(data["features"]))):
    if "label" in data["features"][k]["properties"]:
        del data["features"][k]