为大量对象生成对象唯一索引
我希望你们能帮我解决这个问题:)
我正在尝试为 3D 软件创建 python 对象。这些对象需要有一个有意义的名称,如下所示:L_hello01_EXT,并且是使用每个部分的一些变量生成的。
但是其中的数字(01)应该是自动生成的。其标准是,如果已存在具有相同名称的对象,则将索引加一,直到生成的名称不被任何其他对象使用。
问题是我需要创建大约 20k 个或更多,所以我需要找到一种方法来快速找出最新的可用名称,同时保留对象。
现在我尝试了两种方法:
创建一个空列表并在生成名称时存储它们。然后检查名称是否在 cette 列表中。当该名称在列表中时,将索引增加 1,然后重试。
创建一个空集并向其中添加名称。要检查节点是否存在:复制集合,将节点的名称添加到其中并比较两个集合的长度。如果副本大于原始名称,则名称是新的。
class BasicNode:
node_pool = set()
def __init__(self, side: str, name: str, ihi: bool, **kwargs):
"""Initializes the NodeInfo object of the node, and generates a name for the instance and appends a
the generated instance to the class' node_pool variable."""
# Create NodeInfo instance using default params. For now it will only hold naming info.
self._node_info = NodeInfo(side=side,
inherited_name=name,
ihi=ihi,
**naming_kwargs)
# Build the name of the node using _node_info obj
self._node_info.generated_name = self.__get_first_available_name(self)
# Append to list
self.__class__.node_pool.add(str(self))
@classmethod
def __get_first_available_name(cls, basic_node_inst: "BasicNode"):
node_info_obj = basic_node_inst._node_info
node_info_obj.generated_name = cls.__build_name(node_info_obj.side,
node_info_obj.inherited_name,
node_info_obj.tag,
node_info_obj.count,
node_info_obj.suffix,
node_info_obj.extension)
while objExists(basic_node_inst) is True:
node_info_obj.count += 1
node_info_obj.generated_name = cls.__build_name(node_info_obj.side,
node_info_obj.inherited_name,
node_info_obj.tag,
node_info_obj.count,
node_info_obj.suffix,
node_info_obj.extension)
return node_info_obj.generated_name
def objExists(node_object: BasicNode) -> bool:
incremented_set = node_object.__class__.node_pool.copy()
incremented_set.add(str(node_object))
if len(node_object.__class__.node_pool) == len(incremented_set):
return True
return False
# ==== DUNDER METHODS ===============================================
def __str__(self):
return str(self._node_info.generated_name)
def __repr__(self):
return str(self._node_info.generated_name)
欢迎任何帮助:)
Ty!
I hope you guys can lend me a hand with this one :)
I am trying to create python objects for a 3D software. These objects need to have a meaningful name like the following: L_hello01_EXT and are generated using some variables for each of the parts.
The number in it, however (the 01) should be automatically generated. The criteria for that would be that if an object with that same name already exists, increment the index by one until the generated name isn´t being used by any other object.
The problem is that I need to create about 20k of these or more so I need to find a way to figure out fast the latest available name while keeping the objects.
Right now I have tried 2 methods:
Creating an empty list and storing the names as they are being generated. Then checking
if
the name isin
cette list. While the name is in the list, increase the index by one and try again.Creating an empty set and add the names to it. To check if the node exists: copy the set, add the name of the node to it and comparing both set's length. If the copy is greater than the original, the name is new.
class BasicNode:
node_pool = set()
def __init__(self, side: str, name: str, ihi: bool, **kwargs):
"""Initializes the NodeInfo object of the node, and generates a name for the instance and appends a
the generated instance to the class' node_pool variable."""
# Create NodeInfo instance using default params. For now it will only hold naming info.
self._node_info = NodeInfo(side=side,
inherited_name=name,
ihi=ihi,
**naming_kwargs)
# Build the name of the node using _node_info obj
self._node_info.generated_name = self.__get_first_available_name(self)
# Append to list
self.__class__.node_pool.add(str(self))
@classmethod
def __get_first_available_name(cls, basic_node_inst: "BasicNode"):
node_info_obj = basic_node_inst._node_info
node_info_obj.generated_name = cls.__build_name(node_info_obj.side,
node_info_obj.inherited_name,
node_info_obj.tag,
node_info_obj.count,
node_info_obj.suffix,
node_info_obj.extension)
while objExists(basic_node_inst) is True:
node_info_obj.count += 1
node_info_obj.generated_name = cls.__build_name(node_info_obj.side,
node_info_obj.inherited_name,
node_info_obj.tag,
node_info_obj.count,
node_info_obj.suffix,
node_info_obj.extension)
return node_info_obj.generated_name
def objExists(node_object: BasicNode) -> bool:
incremented_set = node_object.__class__.node_pool.copy()
incremented_set.add(str(node_object))
if len(node_object.__class__.node_pool) == len(incremented_set):
return True
return False
# ==== DUNDER METHODS ===============================================
def __str__(self):
return str(self._node_info.generated_name)
def __repr__(self):
return str(self._node_info.generated_name)
Any help is welocome :)
Ty!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
用户@RodrigoRodrigues 建议只为所有实例使用一个计数器,而不是为每个特定模式使用一个计数器。您要求提供一个示例,这是一个简化的示例:
结果:
如果您需要跟踪特定模式的计数,您可以仅使用
dict
,其键是相关字段的元组:结果:
当然,您可以添加复杂性,但基本思想是相同的:保留一个
tuple
到int
的字典,以跟踪之前使用过的组合,并使它们的值成为计数器。在这两个示例中,计数器(int
或dict
)都保留为类属性,这使您可以记住创建之间的值实例。注意:键入不是必需的,它只是为了清楚地说明它是如何工作的。这并没有坏处 - 在 Python 3.9+ 中,您可以只使用
dict
而无需typing.Dict
导入。注意:第一个示例中的
__class__
是为了避免在实例上重新定义unique
,您希望分配给类属性,而不是实例属性。counters
字典不需要这样做,因为它只是被访问,而不是被设置。注意:如果您不熟悉
defaultdict
,它允许您访问之前未添加的值 - 它只会添加类型的默认值,在本例中为int
,因此它在第一次访问时将新条目设置为 0。您可以自己使用一些代码来完成此操作,但为什么不使用库提供的功能呢?User @RodrigoRodrigues suggested just having a single counter for all instances, instead of a counter per specific pattern. You asked for an example, this is a simplified example:
Result:
If you need to keep track of counts for specific patterns, you could just use a
dict
with the key being a tuple of the relevant fields:Result:
Of course you can add complications, but the basic idea would be the same: keep a dictionary of
tuple
toint
to keep track of what combinations have been used before, and make their value a counter. In both examples, the counter (theint
or thedict
) are kept as class attributes, which allows you to remember the value between creation of instances.Note: the typing isn't required, it's just there to make it clear how it works. It doesn't hurt - in Python 3.9+, you'd be able to just use
dict
without thetyping.Dict
import.Note: the
__class__
in the first example is needed to avoid redefiningunique
on the instance, you want to assign to the class attribute, not an instance attribute. That's not needed with thecounters
dictionary, because it's only being accessed, not set.Note: in case you're not familiar with
defaultdict
, it allows you to access a value that hasn't been added before - it will just add the default for the type, in this case anint
, so it sets a new entry to 0 when first accessed. You could do this with some code yourself, but why not use what the libraries have to offer?