Fastest way to get Fcurves from bone?

When trying to get the fcurves associated with a bone, the solution I found was to iterate through all fcurves from the armature and search for this part: pose.bone[“name”] to see which bone it is associated with.
Now if you need to do that in a complex rig, this is obviously quite a lot of loops and I was wondering if there is a faster way.

for bone in selectedBones:
    fcurves = []
    for fcurve in armature.animation_data.action.fcurves:
        if bone.name == fcurve.data_path.split('"')[1]:
            fcurves.append(fcurve)
    # do something with fcurves

Try this:

# assumes selected_bones is a list of selected bones...

bone_names_list = [b.name for b in selected_bones]
fcurves = armature.animation_data.action.fcurves
fcurves_selected = [f for f in fcurves if f.data_path.split('"')[1] in bone_names_list]

Not tested, I have no time, but this method of building lists works for me.

Salut, Clock.

If i read this right, this would only get me the fcurves for one bone. however i’d need it for multiple bones
I sort the fcurves into a dict now before i use them, that should save me a ton of loops and make things faster.

sorted_fcurves = {}
for fcurve in armature.animation_data.action.fcurves:
     if fcurve.data_path.split('"')[1] in sorted_fcurves:
          sorted_fcurves[fcurve.data_path.split('"')[1]].append(fcurve)
     else:
          sorted_fcurves[fcurve.data_path.split('"')[1]] = [fcurve]
            
for bone in selected_bones:
     # do something with sorted_fcurves[bone.name]

No, it gives a list of all the Fcurves in all the selected bones. The comprehension of type:

[f for f in fcurves if f.data_path.split('"')[1] in bone_names_list]

gives a list of all the Fcurves in all the bones whose name appears in the list bone_name_list, not just one of them. This construct looks in the list to see if the name is there and adds all its Fcurves to the list of Fcurves. You can sort the list using something along the lines of this:

objs = sorted(context.view_layer.objects.selected, key=lambda x: x.name)

Just change the variables to suit your purposes.

There is no need for any for... loops with this method.

EDIT: See this:

https://python-3-patterns-idioms-test.readthedocs.io/en/latest/Comprehensions.html

EDIT: example, combining two constructs to make a sorted set:

or sort by the third letter:

This construct allows you to work on a subset of out_list (like your individual bone names):