在 C++ 中存储和检索多个密钥

发布于 2024-09-24 04:45:37 字数 148 浏览 1 评论 0原文

我有一些检索值所需的整数键。基于键存储和检索值的最有效方法是什么?

目前,我正在将三个键转换并组合成一个字符串,并将键值对存储在映射中。但是,我认为应该有一种更有效的方法来仅基于整数值来执行此操作,例如基于三个键生成单个键。对此有什么想法吗?

谢谢。

I have a few integer keys that is needed to retrieve a value. What is the most efficient way to store and retrieve the value based on the keys?

Currently I am converting and combining the three keys into a single string and store the key-value pair in a map. However, I think there should be a more efficient way of doing that based on the integer value alone for example generating a single key based on the three keys. Any ideas on that?

Thanks.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

春庭雪 2024-10-01 04:45:37

几乎可以肯定,您可以比转换为字符串做得更好(这通常是一个相当慢的操作)。如果您的三个项目的范围足够小,您可以进行一些移位和添加,将它们组合成一个具有更大范围的整数。

如果缺少这一点,您可以创建一个包含三个整数的结构,并定义 operator< 以合理的方式比较它们:

class key { 
    int a, b, c;
public:
    bool operator<(key const &other) { 
        if (a < other.a)
            return true;
        if (a > other.a)
            return false;
        if (b < other.b)
            return true;
        if (b > other.b)
            return false;
        if (c < other.c)
            return true;
        return false;
    }
};

编辑:对于那些关心它的人,使用 (std | tr1 | boost) ::tuple 不会改变答案的特征太多,但会消除大部分代码。元组与 std::pair 非常相似,不同之处在于它支持任意数量的项目而不是仅两个。对于上面的示例,您可以使用类似的内容:

#include <tuple>

namespace stdx = std::tr1;    // or stdx=boost::tr1, etc.

typedef stdx::tuple<int, int, int> key_t;

std::map<key_t, whatever> my_map;

tuple 自动定义比较运算符,假设类型是可比较的(即,用于比较具有相同元素数量的两个元组,并且相应元素的类型是可比较的)。在这种情况下,它进行字典比较(即,比较的结果是第一对不相等的相应元素的结果——如果不存在这样的元素,则两个比较相等)。

You can almost certainly do better than converting to a string (which is generally quite a slow operation). If your three items have small enough ranges, you can do some shifting and adding to put them together into a single integer with a larger range.

Lacking that, you can just create a struct that holds three ints, and defines operator< to compare them in a reasonable fashion:

class key { 
    int a, b, c;
public:
    bool operator<(key const &other) { 
        if (a < other.a)
            return true;
        if (a > other.a)
            return false;
        if (b < other.b)
            return true;
        if (b > other.b)
            return false;
        if (c < other.c)
            return true;
        return false;
    }
};

Edit: for those who care about it, using (std | tr1 | boost)::tuple wouldn't change the character of answer much, but would eliminate most of the code. A tuple is pretty similar to std::pair, except that it supports an arbitrary number of items instead of just two. For the example above, you could use something like:

#include <tuple>

namespace stdx = std::tr1;    // or stdx=boost::tr1, etc.

typedef stdx::tuple<int, int, int> key_t;

std::map<key_t, whatever> my_map;

tuple defines comparison operators automatically assuming the types are comparable (i.e., for comparing two tuples with the same number of elements, and the types of corresponding elements are comparable). In this case it does a lexicographic comparison (i.e., the result of the comparison is the result from the first pair of corresponding elements that are not equal -- of no such element exists, the two compare equal).

相思碎 2024-10-01 04:45:37

Jerry Coffin 的建议很好,它可以扩展到任意数量的任意宽度的键。

然而,在实践中,有很多情况可以采用以下有效方法。如果键的大小使其总和适合本机类型,那么我们可以按如下方式组合键。

假设我们有三个关键部分:

a, 16-bit,
b, 32-bit
c, 16-bit

按重要性顺序列出以进行比较。 (与 Jerry Coffin 的示例相同。)

然后,我们可以

class key {
  private:
    uint64_t key_rep_;  // internal key representation
};

通过 key_rep_ 的以下底层解释

AAAABBBBBBBBCCCC

获得一个值上面的每个字母都是一个半字节,并显示了它所代表的关键部分。

将此方法与直接方法进行比较:

  • 在键中读取和写入键部分较慢
  • 比较两个键更快

在映射或集合中,键的比较比读/写更频繁,因此此方法在适用时可以实现整体效率。

Jerry Coffin's suggestion is a nice one, it is extensible to any number of keys of arbitrary width.

However, in practice, there are many situations where the following efficient method can be employed. If the size of the keys are such that their sum fits into a native type, then we can compose the key as following.

Suppose we have three key-parts:

a, 16-bit,
b, 32-bit
c, 16-bit

listed in the order of significance for comparison. (Same as in example of Jerry Coffin.)

Then, we can have one value

class key {
  private:
    uint64_t key_rep_;  // internal key representation
};

with the following underlying interpretation of key_rep_

AAAABBBBBBBBCCCC

Each letter above is a nibble, and shows the key-part it represents.

Comparing this approach with the straightforward one:

  • reading and writing key-part into the key are slower
  • comparing two keys are faster

In a map or set, comparison of keys are much more frequent than read/write, so this approach, when applicable, achieves overall efficiency.

半世蒼涼 2024-10-01 04:45:37

您可以使用映射将带有键的向量映射到值,并对映射使用字典顺序。如果键的数量是恒定的,您甚至可以使用相同的顺序映射 int 数组

you can map a vector with the keys to the value with a map and use a lexicographical ordering for the map. If the number of keys is constant you can even map arrays of int with the same ordering

-小熊_ 2024-10-01 04:45:37

你正在做的事情听起来不错。您可能会想到的另一种方法是使用从三个整数子项生成的哈希码来通过类似 unordered_map

如果 std::map 适合您并且不需要 O(1) 查找时间,那么迁移到基于哈希的容器可能会导致哈希代码生成变得复杂(不容易做好) )这让它带来的麻烦超过了它的价值。

What you are doing sounds fine. An alternative that you may be feeling your way towards would be to use a hash code generated from your three integer subkeys to access the values via something like unordered_map.

If the std::map is working for you and you don't need O(1) lookup time, moving to a hash-based container could introduce complexity in hash code generation (not easy to do well) that makes it more trouble than it is worth.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文