index lookup in a collection

below a collection :

import bpy

class elements(bpy.types.PropertyGroup) :
    name  = bpy.props.StringProperty()
    type  = bpy.props.StringProperty()
   <b> # id = bpy.props.IntProperty() that copy the collection index at creation time ?</b>

    <b>def index(self) : # slow.. redundant ?</b>
        elements = bpy.context.scene.elements
        for i,elm in enumerate(elements) :
            if elm.name == self.name :
                return i
    
bpy.utils.register_class(elements)        
bpy.types.Scene.elements = bpy.props.CollectionProperty(type=elements)
elements = bpy.context.scene.elements

supposing a big collection of ‘elements’…


for i in range(10000) :
    elm = elements.add()
    elm.name='name %s'%i

of course in real life the elm name does not match the elm index number.
how can I retrieve quickly the index of an element from its name ?

name = 
elm = elements['name 8997']
print( elm.index() )

why I think I’m missing something … the index is known, of course, internally…:

&gt;&gt;&gt; city.element['building.0000']
bpy.data.scenes["Scene"].city.element[<b>0</b>]

You can…
http://docs.python.org/tutorial/datastructures.html

P.S. I posted the link so you’d see other available features and ways…

ahaha.
except I need this in a BPY collection

…sorry
I know list.index() is fast. but here it’s a bpy collection. internally the index is known when you access one of the member by its name. so I could add a list with names for lookup sure, but there must be a way to access the index internally.

I was going to say I see what you mean:


import bpy

o=bpy.context.selected_objects

n=len(o)
n=int(n/2)

oo=o[n]

print("1.",oo.name)

if oo in o:
    print("true")
    #print("1.",o[oo.name])
    #print("1.",o[oo])
    #k=o.keys()

As in a bpy collection isn’t a Dictionary.

I was going to suggest saving the index when you extract it…


ob=(n,o[n])

But now i’m unsure again, so…

(I need sleep, but), Once you take an element out of the list it has no connection with the list… Maybe someone else can answer this next bit, but is there pointers in Python??? (err)

here is a paper about bpy collection :
http://www.blender.org/documentation/blender_python_api_2_57_release/bpy.props.html#collection-example

in fact this don’t take the element out of the collection, it’s ‘linked’ like w/ a dict

elm = element['name']
elm.name = 'spam'
elm.xxxx = True # with xxx a bpy.props you defined in the class

I finally wrote this fast and strange thing (index2 class function). a little benchmark below (toggle the console, wait a bit a first exec)
anyway, bpy collection will certainly offer an index() method, this is just a workaround meanwhile.

import bpy
import time

class elements(bpy.types.PropertyGroup) :
    type  = bpy.props.StringProperty()
    <b># a 'name' stringProp is added by default</b>

    def index(self) : # slow
        elements = bpy.context.scene.elements
        for i,elm in enumerate(elements) :
            if elm.name == self.name :
                return i
<b>    def index2(self) : # fast and dirty
        return int(self.path_from_id().split('[')[1].split(']')[0])</b>
    
bpy.utils.register_class(elements)        
bpy.types.Scene.elements = bpy.props.CollectionProperty(type=elements)
elements = bpy.context.scene.elements


if len(elements) == 0 :
    print('feeding collection...')
    for i in range(20000) :
        elm = elements.add()
        elm.name  = 'name %s'%i
        elm.type  = 'mytype'
    print('done.')

elm = elements['name 19999']
t0 = time.time()
print('index of %s is %s (%s)'%(elm.name,<b>elm.index()</b>,time.time()-t0))

t0 = time.time()
print('index of %s is %s (%s)'%(elm.name,<b>elm.index2()</b>,time.time()-t0))

Your ‘slow’ version will be similar to how it’s done in the compiled C or C++ code of Python.

For your tests, i’d put them in a loop and run them a few thousand times and calculate the average from the overall time and then only print the results, just because of the way computers work. (Not that this contains the line i’m looking for, Tron MCP)

I agree…

Your ‘slow’ version will be similar to how it’s done in the compiled C or C++ code of Python.

if collection indexes are solved this way for bpy collection. do you agree that

&gt;&gt;&gt; city.element['building.0000']
bpy.data.scenes["Scene"].city.element[0]

would be faster than :

&gt;&gt;&gt; city.element['building.99999999']
bpy.data.scenes["Scene"].city.element[99999999]

?
well… I’ll let you try, but I’m pretty sure the response time will be the same.

It depends on various things, personally I don’t know the way it’s set up internally, here’s the basic available types of collections in STL:
http://www.cplusplus.com/reference/stl/

Underlying they will use linked lists and may need to iterate through to find an index since they may not be stored that way. But since you have shown that the list is fairly simple and can’t be accessed by name other than via a separate function, it’s probably a doubly linked circular list or similar. Because the physical memory may not be stored consecutively each item stores a pointer to the next (and previous) item in the list, meaning it will probably take the same number of operations to get to the same place (the comparator function would probably be different). Sorry I never really went in for O notation but I think it’d be the same…

P.S. I’ve not re-read that 'cos i’m hungry, and no, i’ve never studied computers or programming anywhere other than by myself, so… I may be wrong!