Closed strohne closed 11 years ago
Mal auf deutsch, weil gerade schneller:
def getDictValue(data,multikey):
keys=multikey.split('.')
value=data
for key in keys:
if type(value) is dict:
value=value.get(key,"")
elif type(value) is list:
valuelist=[]
for elem in value:
if key in elem:
valuelist.append(elem[key])
else:
valuelist.append(elem)
return ";".join(str(vlelem) for vlelem in valuelist)
else:
return ""
if type(value) is dict:
return json.dumps(value)
else:
return value
eval()
könnte man auch direkt python-Ausdrücke auswerten, z. B. sowas wie entities.urls[i for i in url] bei Tweets; vermutlich aber overkillDu fragst: Wo findet eigentlich die Iteration hier statt?
Antwort: die Iteration findet über die keys statt, also in deinem Beispiel über [user,entities]. Zuerst wird value auf den input gesetzt. Nach der ersten Iteration ist value der Wert in user, nach der zweiten Iteration ist value der Wert von user.entities. Dann wirt erst returned. Die Iteration gräbt sich gewissermaßen in das JSON rein.
Habe mich gerade auch über einen Satz in der Hilfe gewundert: "Using nested columns like "user.entities.url.urls" (for Twitter Tweets) may have no effect in the object view". -> das sollte auf jeden Fall einen Effekt haben, läuft über die gleiche Funktion. Bist Du sicher? Kannst Du mir ggf. ein reproduzierbares Beispiel geben (welches Query)?
Ich glaube Deine Funktion geht so nicht, das müsste man rekursiv lösen, weil ja für jedes Listenelement der Inhalt auch auf tieferen Ebenen ausgelesen werden soll.
Ich überlege mir morgen mal was, falls Du nicht schon eine Lösung hast.
Noch eine Idee: ich fände es besser, wenn der key bei Listen entweder wie bisher als Index (0,1 etc.) oder als Wildcard (* oder n) angegeben werden muss. Dann kann man sowohl einzelne Items als auch alle Items (und vielleicht auch noch die Liste in JSON-Format) ausgeben.
Ja, das wäre tatsächlich gut oder die Ideallösung! Wenn man die Inhalte auf tieferen Elementen auslesen möchte, muss man denke ich eine Reukrusion bauen und eine Funktion nochmal aufrufen (am optimalsten sogar irgendwie als Generator?).
Ich hatte mal eine alte Funktion, um nested Dicts auszulesen (die ist aber auch noch optimierbar; nester() ) und als Iterator/Generator verwendbar (lookup() ). Vielleicht kann man die beiden nutzen (ein paar Dinge wie das "$t" kann man rausnehmen, das ist YouTube-spezifisch. Kann mir aber auch noch mal Gedanken machen. So low-level Funktionen finde ich eh immer ganz spannend :)
def nester(d, k):
if isinstance(d, dict):
if d.get(k, None) is not None:
try:
if d[k].get('$t', None) is not None:
yield d[k]['$t']
else:
yield d[k]
except:
yield d[k]
for subdict in d:
for dictocc in nester(d[subdict], k):
yield dictocc
if isinstance(d, list):
for elems in d:
for listocc in nester(elems, k):
yield listocc
Und hier der lookup bzw die Verwendung als Generator:
def lookup(d, k):
try:
return [l for l in nester(d, k)].pop()
except IndexError:
return None
Siehe eines der letzten Commits.
Habe vorhin die Methode überarbeitet. Schau doch mal, ob die das so macht wie du es gerne hättest. Siehe auch die commit message.
Sieht sehr gut aus, funktioniert zumindest alles in meinem Tests!
Display lists in single columns or unpack lists into new datasets.