sortedcontainers。SortedKeyList:返回具有匹配值的元素

sortedcontainers.SortedKeyList: Return Element with Matching Value of Key

提问人:user2514157 提问时间:10/22/2023 更新时间:10/26/2023 访问量:36

问:

我用来存储字典列表。字典在列表中按(嵌套)键的值(即“token_str”)排序。sortedcontainersSortedKeyList

它似乎已正确存储在(例如,如下所示)中,该已通过调试器进行了验证。SortedKeyListself.tokenized_files

但是,当我尝试从列表中检索具有给定键值(即 token_str)的元素(即字典)时,我得到 .TypeError: string indices must be integers, not 'str'

如何使用嵌套键的值从 SortedKeyList 中检索元素(即字典)?优选地,使用有效的搜索算法,例如平分,而不是遍历整个列表。

self.sorted_index_by_token_str = None
self.tokenized_files = SortedKeyList([
                {'full_path': '/path/to/file/mdb_00033k__filename1.pdf', 'tokenized_filename': {'basic_filename': 'filename1.pdf', 'token': {'token_str': 'mdb_00033k'}}},
                {'full_path': '/path/to/file/mdb_0027zz__filename2.pdf', 'tokenized_filename': {'basic_filename': 'filename2.pdf', 'token': {'token_str': 'mdb_0027zz'}}},
            ])
               

def generate_index(self) -> SortedKeyList:
    """Creates an index comprising a list of dicts of tokenized files sorted by token_str.
    """

    self.sorted_index_by_token_str = SortedKeyList(
        self.tokenized_files,
        key=lambda x: x["tokenized_filename"]["token"]["token_str"],
    )
    # Evaluate: x["tokenized_filename"]["token"]["token_str"]
    # Returns: 'mdb_0027zz'
    return self.sorted_index_by_token_str


def find_tokenized_file(self) -> dict:
    """Finds a tokenized file in the index by performing a binary search on token_str.
    """

    test = self.sorted_index_by_token_str.index("mdb_0027zz")


# ERROR:
# test = self.sorted_index_by_token_str.index("mdb_0027zz")
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
# key = self._key(value)
# ^^^^^^^^^^^^^^^^
# key=lambda x: x["tokenized_filename"]["token"]["token_str"],
# ~^^^^^^^^^^^^^^^^^^^^^^
# TypeError: string indices must be integers, not 'str'```
排序 搜索 列表 排序容器

评论


答:

0赞 user2514157 10/23/2023 #1

键必须是整个嵌套字典(而不仅仅是我认为的简单键值)。然后,该方法用于确定元素的索引,并随后进行检查以确认位于索引处的元素是否与键值匹配。bisect_left


       self.sorted_index_by_token_str = SortedKeyList(
            key=lambda x: x["tokenized_filename"]["token"]["token_str"]
        )

        key = {"tokenized_filename": {"token": {"token_str": token_str}}}
        index = self.sorted_index_by_token_str.bisect_left(key)

        # Check if the token_str is found at the returned index
        if (
            index < len(self.sorted_index_by_token_str)
            and self.sorted_index_by_token_str[index]["tokenized_filename"]["token"][
                "token_str"
            ]
            == token_str
        ):
            return self.sorted_index_by_token_str[index]

        # token_str not found
        return None

或者,使用 bisect_key_left(每@user2357112):

from bisect import bisect_key_left

key = {"tokenized_filename": {"token": {"token_str": token_str}}}
index = bisect_key_left(self.sorted_index_by_token_str, key, key=lambda x: x["tokenized_filename"]["token"]["token_str"])

# Check if the token_str is found at the returned index
if (
    index < len(self.sorted_index_by_token_str)
    and self.sorted_index_by_token_str[index]["tokenized_filename"]["token"][
        "token_str"
    ]
    == token_str
):
    return self.sorted_index_by_token_str[index]

# token_str not found
return None

评论

0赞 user2357112 10/24/2023
您可能还想查看 bisect_key_left 和 。bisect_key_right
0赞 user2514157 10/24/2023
@user2357112我一直在努力完全理解 sortedcontainers 文档,并感谢您的建议。 似乎更明显地适合这种情况,但我在实践中没有看到显着差异。我是否误解了它的使用方式?bisect_key_left
1赞 user2357112 10/24/2023
我说的是方法,你会像.没有.(当你在做这件事时,你不需要调用已经是字典的东西,也不需要在已经是字符串时用它来获取字符串。SortedKeyListindex = self.sorted_index_by_token_str.bisect_key_left(token_str)bisect.bisect_key_leftdictf"{token_str}"token_str