2016-07-14 7 views
1

Ich bin ziemlich neu in Python und ich versuche, Filterabfrage als mein Endergebnis mit einem Wörterbuch mit n-Tiefe aufzubauen. Im Inneren könnte es andere Wörterbücher und Listen geben.Wie kann ich ein tief verschachteltes Wörterbuch durchqueren, das in Python Listen und andere Wörterbücher enthält?

Dies ist meine Struktur:

filters = { 
    predicate: 'AND', 
    filters: [ 
     {'property_class_id': 10, operator: 'contains', operands: ['FOO']}, 
     { 
      predicate: 'NOT', 
      filters: [{ 
       predicate: 'OR', 
       filters: [ 
        {'property_class_id': 1, operator: 'contains', operands: ['Hello']}, 
        {'property_class_id': 2, operator: 'contains', operands: ['my search term']} 
       ] 
      }] 
     }, 
     { 
      predicate: 'OR', 
      filters: [ 
       {'property_class_id': 3, operator: 'contains', operands: ['my search term']}, 
       {'property_class_id': 4, operator: 'contains', operands: ['my search term']} 
      ] 
     } 
    ] 
} 

Ich hoffe, ich dies auf A + übersetzen würde (B oder C) + (D oder E) mit Q-Objekte!.

Mein erstes Problem ist jedoch, wie durchlaufe ich dieses Wörterbuch durch jedes Schlüsselwertpaar?

Dies ist, was ich bisher habe, aber Sie können die Begrenzung sehen, sobald ich eine Liste triff, da die for-Schleife nur Wörterbücher akzeptiert.

def unpack_filter(self, filters): 
    q_object = Q() 
    q_list = [] 

    for key, value in filters.iteritems(): 
     if isinstance(value, list) or isinstance(value, dict): 
      self.unpack_filter(value) 
     else: 
      print "{0} : {1}".format(key, value) 

Antwort

0

Ich habe die Struktur ein kleines bisschen verändert, um es laufen zu lassen. Sie können einfach die modifizierte unpack_filter Schleife in Ihren Code integrieren:

base_filter = { 
    'predicate': 'AND', 
    'filters': [ 
    {'property_class_id': 10, 'operator': 'contains', 'operands': ['FOO']}, 
    { 
     'predicate': 'NOT', 
     'filters': [{ 
     'predicate': 'OR', 
     'filters': [ 
      {'property_class_id': 1, 'operator': 'contains', 'operands': ['Hello']}, 
      {'property_class_id': 2, 'operator': 'contains', 'operands': ['my search term']} 
     ] 
     }] 
    }, 
    { 
     'predicate': 'OR', 
     'filters': [ 
     {'property_class_id': 3, 'operator': 'contains', 'operands': ['my search term']}, 
     {'property_class_id': 4, 'operator': 'contains', 'operands': ['my search term']} 
     ] 
    } 
    ] 
} 

# try to avoid using/overwriting the 'filter' name as it's a built-in function 
# https://docs.python.org/2/library/functions.html#filter 
# this is why I'm using names such as 'curr_filter' and 'f' 

def unpack_filter(curr_filter): 
    # ... do something with curr_filter['predicate'] ... 
    for f in curr_filter['filters']: 
    if 'filters' in f: 
     unpack_filter(f)  
    else: 
     for key, value in f.iteritems(): 
     print '{0} : {1}'.format(key, value) 

unpack_filter(base_filter) 
0

Wie in der vorherigen Antwort erklärt Ihnen die entweder durch Tasten in einem Wörterbuch oder Elemente in einer Liste ‚in‘ Operator Schleife verwenden können. Auf diese Weise können Sie eine Schleife mit if-Anweisungen erstellen, die entscheiden, wie Sie reagieren sollen. Die obige Antwort gibt die Schlüssel und Werte der innersten Wörterbücher aus, die Sie möglicherweise möchten. Hier ist eine weitere Option, die die Werte der Wörterbücher nur dann ausgibt, wenn "Filter" oder "Prädikate" kein Schlüssel sind. Sie können dann ** kwargs verwenden und die innersten Wörterbücher, wenn sie richtig strukturiert sind, direkt an das Q() -Objekt übergeben, um Schlüsselwortargumente für die Abfrage zu erstellen.

def unpack_filter(curr_filter): 
    for f in curr_filter: 
    if f == 'filters': 
     unpack_filter(curr_filter[f]) 
    elif f == 'predicate': 
     print curr_filter[f] 
    elif 'filters' in f or 'predicate' in f: 
     unpack_filter(f) 
    else: 
     print f 

Hier ist ein einfaches Beispiel ein Wörterbuch als Keyword-Argumente übergeben:

filters = {'name__icontains': 'Google'} 
def f(**kwargs): 
    val = kwargs.pop('name__icontains') 
    print val 

# the next two function calls print the same thing 
f(**filters) 
f(name__icontains='Google') 
Verwandte Themen