HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Nested array-to-dict transformation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
arraynesteddicttransformation

Problem

I'm looking to let people define arbitrarily nested lists of lists and return a random json document for them. Right now the assumption is that if you have a structure like this:

[item1, item2, [item3, item4]]


The desired document is:

{item1: value,
item2: {
    item3: value,
    item4: value
    }
}


This is my current solution:

def random_document(document_layout, type_, **kwargs):
    document_layout.append("dummy_item")
    doc = lambda l:{l[i]:doc(l[i+1]) if isinstance(l[i+1],list) else random_item(type_,**kwargs) for i in range(len(l)-1)}
    return doc(document_layout)


as a one line fetishist, I feel like the middle line is beautiful, but I think the general hack of adding a dummy element to the end is hackish. Any thoughts on how to make this more elegant?

Also, not looking for deeply readable, this is just for my own private use and isn't going to spread out in any meaningful way, so I would just like to preempt the commentary about it not being readable.

Here's a more "readable" version:

def random_document(document_layout, type_, **kwargs):
    document_layout.append("dummy_item")
    full_dict = {}
    def internal_comprehension(document):
        for i in range(len(document)-1):
            if isinstance(document[i+1], list):
                full_dict.update({document[i]: internal_comprehension(document[i+1])})
            else:
                full_dict.update({document[i]: random_item(type_, **kwargs)})
    return internal_comprehension(document_layout)

Solution

Your one-liner is too unreadable for my taste. Furthermore, neither version actually works.

The fundamental obstacle to elegance is that the problem requires you to look ahead one element to interpret how to handle the current element.

def random_document(document_layout, type_, **kwargs):
    def internal_comprehension(document):
        full_dict = {}
        for i in range(len(document)):
            if isinstance(document[i], list):
                # This item should have already been processed in a previous
                # recursive call to internal_comprehension()
                pass
            elif i == len(document) - 1 or not isinstance(document[i+1], list):             
                # This item is an independent item
                full_dict.update({document[i]: random_item(type_, **kwargs)})               
            else:
                # Next item is a list, so create a level of nesting
                full_dict.update({document[i]: internal_comprehension(document[i+1])}) 
        return full_dict
    return internal_comprehension(document_layout)


On the other hand, if you iterate through the document_layout backwards, then you don't have a look-ahead problem. Here's how it could look like:

def random_document(document_layout, type_, **kwargs):
    dict = {}
    iter = reversed(document_layout)
    for k in iter:
        if isinstance(k, list):
            dict[iter.next()] = random_document(k, type_, **kwargs)
        else:
            dict[k] = random_item(type_, **kwargs)
    return dict

Code Snippets

def random_document(document_layout, type_, **kwargs):
    def internal_comprehension(document):
        full_dict = {}
        for i in range(len(document)):
            if isinstance(document[i], list):
                # This item should have already been processed in a previous
                # recursive call to internal_comprehension()
                pass
            elif i == len(document) - 1 or not isinstance(document[i+1], list):             
                # This item is an independent item
                full_dict.update({document[i]: random_item(type_, **kwargs)})               
            else:
                # Next item is a list, so create a level of nesting
                full_dict.update({document[i]: internal_comprehension(document[i+1])}) 
        return full_dict
    return internal_comprehension(document_layout)
def random_document(document_layout, type_, **kwargs):
    dict = {}
    iter = reversed(document_layout)
    for k in iter:
        if isinstance(k, list):
            dict[iter.next()] = random_document(k, type_, **kwargs)
        else:
            dict[k] = random_item(type_, **kwargs)
    return dict

Context

StackExchange Code Review Q#29557, answer score: 3

Revisions (0)

No revisions yet.