add elements to indexed list locations

Peter Otten __peter__ at web.de
Sat Jun 17 04:28:21 EDT 2006


levent wrote:

> Thanks for the answers. Enumerating in reverse is indeed quite a smart
> idea.
> 
> The fact is though, I overly simplified the task in the super-hero
> example. In the real case, the dictionary keys are not necessarily the
> indices for inserts; that is to say, the inserts do not necessarily
> take place in some sorted order.
> 
> I think I was thinking more of a linked-list idea, where you do not
> store the indices as integers to some random access array but rather as
> pointers into list's nodes. Then the subsequent inserts would not hurt
> previously stored pointers. For those who know a bit C++/STL here is a
> sketch of the idea:
> 
> name_list  heros;
> heros.push_back("clark");
> // ... add the rest
> indexed_name_list surnames;
> surnames.push_back(
>    make_pair(   find( heros.begin(), heros.end(), "clark"), "kent")   )
>    );  // the find function returns an iterator to appropriate location
> // ... add the rest
> 
> for_each(surnames.begin(), surnames.end(), insert_surnames)
> // insert_surnames is a callback that receives a single indexed surname
> // at a time and does the job, without affecting outer iterators.
> 
> 
> I was wondering how to make indices as *robust* in Python... Any ideas?

Python's list is technically a vector. You can therefore either search for
the insertion point in a timely fashion:

heros = ["super", "clark", "spider", "peter", "bat", "bruce"]
names = [("clark", "kent"), ("peter", "parker"), ("bruce", "wayne")]

for first, last in names:
    heros.insert(heros.index(first)+1, last)
print heros

or you have to snatch a real (linked) list from somewhere. Here's an ad-hoc
implementation:

class Node(object):
    def __init__(self, value, next=None):
        self.value = value
        self.right = next
    def __str__(self):
        return "List(%s)" % ", ".join(repr(n.value) for n in self)
    def __iter__(self):
        item = self
        while item:
            yield item
            item = item.right
    def find(self, value):
        for item in self:
            if item.value == value:
                return item
        raise ValueError("%r not found" % (value,))
    def insert_after(self, value):
        self.right = Node(value, self.right)
    @staticmethod
    def from_list(items):
        items = iter(items)
        try:
            first = items.next()
        except StopIteration:
            raise ValueError("empty lists not supported")
        cur = head = Node(first)
        for value in items:
            node = Node(value)
            cur.right = node
            cur = node
        return head

if __name__ == "__main__":
    heros = ["super", "clark", "spider", "peter", "bat", "bruce"]
    heros = Node.from_list(heros)
    names = [("clark", "kent"), ("peter", "parker"), ("bruce", "wayne")]
    surnames = [(heros.find(f), s) for f, s in names]
    print heros
    for node, value in surnames:
        node.insert_after(value)
    print heros

Peter




More information about the Python-list mailing list