혼합 유형, 목록 및 사전의 중첩 된 json 개체를 병합하기 위해 재귀 생성기 함수를 작성하려고합니다. 나는 내 자신의 학습을 위해 이것을 부분적으로하고 있기 때문에 인터넷에서 어떤 일이 벌어지고 있는지 더 잘 이해할 수 있도록 예제를 포착하는 것을 피할 수는있다.하지만 막연한 결과를 낳았다. 고리.재귀 생성기 함수 Python 중첩 JSON 데이터
생성기 함수에 전달 된 데이터 원본은 mongo 컬렉션을 반복하는 외부 루프의 출력입니다.
Yield 문과 같은 위치에서 print 문을 사용했을 때 기대했던 결과를 얻었지만 yield 문으로 전환하면 생성자가 외부 루프의 반복마다 하나의 항목 만 생성하는 것처럼 보입니다.
내가 잘못 가고있는 곳을 누군가가 나에게 보여줄 수 있기를 바랍니다.
columns = ['_id'
, 'name'
, 'personId'
, 'status'
, 'explorerProgress'
, 'isSelectedForReview'
]
db = MongoClient().abcDatabase
coll = db.abcCollection
def dic_recurse(data, fields, counter, source_field):
counter += 1
if isinstance(data, dict):
for k, v in data.items():
if k in fields and isinstance(v, list) is False and isinstance(v, dict) is False:
# print "{0}{1}".format(source_field, k)[1:], v
yield "{0}{1}".format(source_field, k)[1:], v
elif isinstance(v, list):
source_field += "_{0}".format(k)
[dic_recurse(l, fields, counter, source_field) for l in data.get(k)]
elif isinstance(v, dict):
source_field += "_{0}".format(k)
dic_recurse(v, fields, counter, source_field)
elif isinstance(data, list):
[dic_recurse(l, fields, counter, '') for l in data]
for item in coll.find():
for d in dic_recurse(item, columns, 0, ''):
print d
아래는 반복되는 데이터의 샘플이지만 중첩은 표시된 것보다 증가합니다. 나는 그들이 정말 아무것도 변경했습니다 내가가 디버거에서 라인으로 라인을 통해 스테핑 봤는데되지 확신하지만
{
"_id" : ObjectId("5478464ee4b0a44213e36eb0"),
"consultationId" : "54784388e4b0a44213e36d5f",
"modules" : [
{
"_id" : "FF",
"name" : "Foundations",
"strategyHeaders" : [
{
"_id" : "FF_Money",
"description" : "Let's see where you're spending your money.",
"name" : "Managing money day to day",
"statuses" : [
{
"pid" : "54784388e4b0a44213e36d5d",
"status" : "selected",
"whenUpdated" : NumberLong(1425017616062)
},
{
"pid" : "54783da8e4b09cf5d82d4e11",
"status" : "selected",
"whenUpdated" : NumberLong(1425017616062)
}
],
"strategies" : [
{
"_id" : "FF_Money_CF",
"description" : "This option helps you get a picture of how much you're spending",
"name" : "Your spending and savings.",
"relatedGoals" : [
{
"_id" : ObjectId("54784581e4b0a44213e36e2f")
},
{
"_id" : ObjectId("5478458ee4b0a44213e36e33")
},
{
"_id" : ObjectId("547845a5e4b0a44213e36e37")
},
{
"_id" : ObjectId("54784577e4b0a44213e36e2b")
},
{
"_id" : ObjectId("5478456ee4b0a44213e36e27")
}
],
"soaTrashWarning" : "Understanding what you are spending and saving is crucial to helping you achieve your goals. Without this in place, you may be spending more than you can afford. ",
"statuses" : [
{
"personId" : "54784388e4b0a44213e36d5d",
"status" : "selected",
"whenUpdated" : NumberLong(1425017616062)
},
{
"personId" : "54783da8e4b09cf5d82d4e11",
"status" : "selected",
"whenUpdated" : NumberLong(1425017616062)
}
],
"trashWarning" : "This option helps you get a picture of how much you're spending and how much you could save.\nAre you sure you don't want to take up this option now?\n\n",
"weight" : NumberInt(1)
},
업데이트 나는, 발전기 기능을 일부 변경했습니다 인쇄 버전과 출력 버전. 새로운 코드는 아래와 같습니다.
def dic_recurse(data, fields, counter, source_field):
print 'Called'
if isinstance(data, dict):
for k, v in data.items():
if isinstance(v, list):
source_field += "_{0}".format(k)
[dic_recurse(l, fields, counter, source_field) for l in v]
elif isinstance(v, dict):
source_field += "_{0}".format(k)
dic_recurse(v, fields, counter, source_field)
elif k in fields and isinstance(v, list) is False and isinstance(v, dict) is False:
counter += 1
yield "L{0}_{1}_{2}".format(counter, source_field, k.replace('_', ''))[1:], v
elif isinstance(data, list):
for l in data:
dic_recurse(l, fields, counter, '')
디버깅 할 때 두 버전의 주요 차이점은이 코드 섹션에 도달했을 때의 것입니다. 내가 항복 버전을 테스트입니다 경우
elif isinstance(data, list):
for l in data:
dic_recurse(l, fields, counter, '')
는 dic_recurse(l, fields, counter, '')
라인에 대한 호출의 히트 얻을하지만 내가 함수의 개막식에서 설정 한 인쇄 문은 충돌하지 않기 때문에 함수를 호출하지 않는 것,하지만 경우 코드가 동일한 섹션에 도달하면 함수를 호출하고 전체 함수를 통해 다시 실행됩니다.
아마 발전기와 yield 문 사용에 대한 근본적인 오해가있을 것입니다.