A way to re-organize a list

beginner zyzhu2000 at gmail.com
Tue Jul 31 21:33:49 EDT 2007


On Jul 19, 10:05 am, beginner <zyzhu2... at gmail.com> wrote:
> Hi Everyone,
>
> I have a simple list reconstruction problem, but I don't really know
> how to do it.
>
> I have a list that looks like this:
>
> l=[ ("A", "a", 1), ("A", "a", 2), ("A", "a", 3), ("A", "b", 1), ("A",
> "b", 2), ("B", "a", 1), ("B", "b", 1)]
>
> What I want to do is to reorganize it in groups, first by the middle
> element of the tuple, and then by the first element. I'd like the
> output look like this:
>
> out=[
>    [    #group by first element "A"
>           [("A", "a", 1), ("A", "a", 2), ("A", "a", 3)], #group by
> second element "a"
>           [ ("A", "b", 1), ("A", "b", 2)], #group by second element
> "b"
>    ],
>    [   #group by first element "B"
>           [("B", "a", 1)],
>           [("B", "b", 1)]
>    ]
> ]
>
> All the solutions I came up with are difficult to read and even harder
> to go back and change, and I just feel are too complicated for such a
> simple problem. I am wondering if anyone here has some insight.
>
> If there is a 'functional' way to do this, it would be even greater.
>
> Thanks,
> Geoffrey

I guess I still don't quite get functional programming. Here is my
imperitive way to do it in O(n).

"""Put a sorted hirerchical structure into nested groups"""

def group_items(source_list, f_list, target=[]):
    """Group_items: Group a list based on the grouping functions.

    source_list is a list or iterator that produces a stream of source
records.

    f_list is a list of functions. Each function takes the form
f(a,b), where
    a and b are two records. If the two records should be in the same
group, it returns
    True, otherwise it returns False.

    If target is not provided, a new list will be created. Otherwise,
the records are
    appended to the provided list.
    """

    last_item=None

    for new_item in source_list:
        level=len(f_list)
        t=target
        for fn in f_list:
            if  t==[] or last_item==None or not fn(last_item,
new_item):
                ng=new_item
                for i in range(level): ng=[ng]
                t.append(ng)
                break
            else:
                t=t[-1]
            level -= 1
        else:
            t.append(new_item)
        last_item=new_item

    return target


if __name__=="__main__":
    import pprint
    def f(a,b):
        return a[0]==b[0]
    def g(a,b):
        return a[1]==b[1]

    mydata=[[1,2,3,4],[1,2,4,5],[1,2,"A","B"],[2,2,"A","C"]]
    t=group_items(mydata, [f,g])
    pprint.pprint(t)






More information about the Python-list mailing list