ตรวจสอบการมีอยู่ของคีย์แบบวนซ้ำและผนวกเข้ากับอาร์เรย์ของ dict

ฉันมีคำสั่งดังต่อไปนี้

{
   "key1" : "value1",
   "key2" : "value2",
   "key3" : "value3",
   "key4" : {
       "key5" : "value5"
   }
}

หาก dict มี key1==value1 ฉันจะเพิ่ม dict ลงในรายการ

สมมติว่า key1==value1 ไม่มีอยู่ในคู่ค่าคีย์คู่แรก ในขณะที่คีย์นั้นอยู่ภายใน dict ที่ซ้อนกันดังนี้:

{
   "key2" : "value2",
   "key3" : "value3",
   "key4" : {
       "key5" : "value5",
       "key1" : "value1",
       "key6" : { 
          "key7" : "value7",
          "key1" : "value1"
       }
   },
   "key8" : { 
       "key9" : "value9",
       "key10" : {
            "key11" : "value11",
            "key12" : "value12",
            "key1" : "value1"
       }
   }
}

ใน dict ข้างต้น ฉันต้องตรวจสอบก่อนว่ามี key1=value1 หรือไม่ ถ้าไม่ ฉันต้องสำรวจ dict ที่ซ้อนกัน และหากพบใน dict ที่ซ้อนกัน ฉันจะต้องเพิ่ม dict นั้นต่อท้ายรายการ หาก dict ที่ซ้อนกันก็เป็น dict ที่ซ้อนกันเช่นกัน แต่พบ key1=value1 ในคู่ของค่าคีย์คู่แรก ก็ไม่จำเป็นต้องตรวจสอบ dict ภายใน (เช่น key4 มี key1=value1 ในคู่ของค่าคีย์คู่แรก ดังนั้น จึงไม่จำเป็นต้อง ตรวจสอบอันด้านในแม้ว่า key6 จะมี key1=value1)

สุดท้ายนี้ผมก็จะมีรายการตามนี้ครับ

[
   {
       "key5" : "value5",
       "key1" : "value1",
       "key6" : { 
          "key7" : "value7",
          "key1" : "value1"
       }
   },
   {
            "key11" : "value11",
            "key12" : "value12",
            "key1" : "value1"
   }
]

จะบรรลุเป้าหมายนี้ได้อย่างไร? หมายเหตุ: ความลึกของ dict อาจแตกต่างกันไป


person NagaLakshmi    schedule 27.03.2015    source แหล่งที่มา
comment
คุณมีคำสั่งเชิงลึกตามอำเภอใจหรืออยู่ในขอบเขตที่จัดการได้เท่านั้น?   -  person syntonym    schedule 27.03.2015
comment
@syntonym สมมติว่ามันเป็นความลึกโดยพลการ ..   -  person NagaLakshmi    schedule 27.03.2015


คำตอบ (1)


หาก dict มี key1 และ value1 เราจะเพิ่มลงในรายการและเสร็จสิ้น ถ้าไม่เช่นนั้น เราจะได้ค่าทั้งหมดใน dict ที่เป็น dict และทำตรรกะเดียวกันด้วย

l = []
def append_dict(d):
    if d.get("key1") == "value1":
        l.append(d)
        return

    for k,v in d.items():
        if isinstance(v, dict):
            append_dict(v) 


append_dict(d)
print l

โซลูชันแบบวนซ้ำจะเพิ่มลงในคิวตาม dict ที่เราต้องการตรวจสอบ:

from Queue import Queue
q = Queue() 
l = []
q.put(d)
while not q.empty():
    d = q.get()
    if d.get("key1") == "value1":
        l.append(d)
        continue
    for k,v in d.items():
        if isinstance(v, dict):
            q.put(v) 

print l

ตามที่ @shashank ระบุไว้ usinq a stack แทนที่จะเป็น queue จะใช้งานได้เช่นกัน BFS vs DFS สำหรับการค้นหาในพจนานุกรม

person Udy    schedule 27.03.2015
comment
if d[k] == vจะไม่เพียงพอหรือ? นอกจากนี้ยังเป็นแบบเรียกซ้ำซึ่งอาจใช้ไม่ได้กับคำสั่งเชิงลึกโดยพลการ (เนื่องจากความลึกของการเรียกซ้ำสูงสุดของ python) แต่อาจจะยังเพียงพอ - person syntonym; 27.03.2015
comment
ขณะที่เขียนคำอธิบายก็สังเกตเห็นเช่นกัน จริงเกี่ยวกับการเรียกซ้ำ จะทำแบบวนซ้ำด้วย - person Udy; 27.03.2015
comment
OP ร้องขอการเรียกซ้ำ - person Moshe Carmeli; 27.03.2015
comment
จริงอยู่ Stack กับ Queue จะเป็น DFS กับ BFS - person Udy; 27.03.2015
comment
คำตอบที่ดี. หมายเหตุ: หากคุณต้องการจำลองลำดับการค้นหาเชิงลึกเป็นอันดับแรกของ LIFO ก็ควรใช้สแต็กแทนคิว หรือใช้ Deque เพื่อจำลองลำดับ ที่แน่นอน ของฟังก์ชันแบบเรียกซ้ำ คิวจะทำการค้นหาแบบกว้างก่อน - person Shashank; 27.03.2015
comment
@MosheCarmeli เขาใช้คำในชื่อเพื่อระบุว่าเขาต้องการสำรวจคำสั่งย่อยทั้งหมด แต่การประมวลผลแบบเรียกซ้ำเข้ากันไม่ได้กับคำสั่งเชิงลึกตามอำเภอใจในหลามในขณะที่วิธีแก้ปัญหาวนซ้ำจะทำงาน ฉันไม่คิดว่าเขาใช้คำว่า recursive ทางเทคนิค แต่เพื่ออธิบายปัญหาของเขา - person syntonym; 27.03.2015