BaseContainer Sort broken?
-
I noticed a weird behvaior on a BC's Sort method. See below.
import c4d if __name__=='__main__': items = {0: "a", 1: "b", 2: "c", 3:"d"} bc = c4d.BaseContainer() for x in items.items(): bc.SetString(x[0], x[1]) bc.Sort() for x in bc: print (x)
This prints out the wrong order:
(1, 'b') (0, 'a') (2, 'c') (3, 'd')
Smells like a bug?
-
Hi @mp5gosu,
thank you for reaching out to us and thank you for pointing out this behaviour. However, this is not a bug, but an intentional feature which is linked to the fact the sub-menu titles will be stored under the ID 1 in a
BaseContainer
. Because of that the method will not be fixed and it is also very unlikely that we will update the documentation, as explaining the reason for this behaviour would require revealing more of the non-public API than we are currently comfortable with.However, since this is an intentional behaviour, you can rely on the fact that this will only happen with the ID 1. I.e., when you place your
BaseContainer
IDs in the range[1, +MAX_INT32]
, the sort method should work like intended.Thank you for your understanding,
Ferdinand -
Okay, thanks for the explanation.
Although it makes sense in this particular context, I see a problem there regarding the general purpose of BaseContainers, since they are widely used.Would it be possible for future API updates to at least provide an optional parameter that the sorting will be in logical order?
Likebc.Sort(natural_range=True)
or something like that? -
Hi @mp5gosu,
I can ask, but I doubt that this will added, because it is ultimately something that can be "fixed" relatively easily from the user side (see end of posting for example). The only meaningful explanation I can give is that
BaseContainer.Sort
was implemented for a very specific reason.BaseContainer
is not really meant to be a replacement for a sortable collection data type.Cheers,
Ferdinand"""A little workaround for the somewhat odd BaseContainer sorting behavior. """ import c4d def cleanSort(bc): """A little helper for BaseContainer.Sort(). """ # Sort the container. bc.Sort() # Get out when the IDs 0 and 1 are not of type string. if (bc.GetType(0) != c4d.DA_STRING or bc.GetType(1) != c4d.DA_STRING): return bc # Save the value of ID 1 valIdOne = bc[1] # Remove the ID 1 and reinsert it in the "right" place. if bc.GetIndexId(0) == 1 and bc.RemoveIndex(0): bc.InsDataAfter(1, valIdOne, bc.GetDataPointer(0)) return bc def main(): """ """ data = {3: "d", 1: "b", 2: "c", 0:"a"} bc = c4d.BaseContainer() for eid, value in data.items(): bc.SetString(eid, value) print ("Before:") for eid, value in bc: print(f"id: {eid}, value:{value}") print ("") bc = cleanSort(bc) print ("After:") for eid, value in bc: print(f"id: {eid}, value:{value}") if __name__=='__main__': main()
-
Hehehe, thanks ferdinand.
Really appreciate your effort.
But in this case, I'll go for the 1st based indexing. Not a big deal.Thanks again!
-
Hi @mp5gosu,
I am sorry to inform you that we talked about the issue, implementing an overloaded version of
BaseContainer::Sort
, and decided that this is not something we want to do in the near future and probably also not at all.Cheers,
Ferdinand -
That's okay, since it is a minor issue.
For newcomers however, there should be a hint in the docs, because it clearly statesSorts the container entries by ID.
which is not the case.