我一直觉得C++编程不方便的一件事是缺少一个好的map/dictionary/hash table/associative array容器类.C#,Java和Objective-C都有这样的类,即Dictionary <>,Hashtable和NSDictionary,它们大多数都是开箱即用的,具有所有数据类型.但是STL的stl :: map和Boost的boost :: unordered_map都非常笨拙且过于冗长,即使对于平凡的日常任务也是如此.我想知道在一些开源库中是否存在C++等价物,它更类似于上述平台的语法和功能.在这三个中,C#的Dictionary <>是我最喜欢的,因为它是强类型的,语法非常短,而且非常通用.所以这样的事情会很完美.我不确定这是否可行.如果没有,我想知道原因.以下是关于Boost和STL实现的主要痛点以及我想要的内容:
首先,性能不是问题.内存分配,虚函数调用,O(n)复杂度 - 无所谓.无论如何,每天的词典只有几个条目.易用性至关重要.
语法通常应该类似于数组.这意味着一个多功能的操作员[],如:
字典[key] =价值; //插入和更新字典[key] = NULL; //删除元素if(dictionary [key])//检查元素是否存在.不应插入默认构造的值!
Java和Objective-C没有运算符重载,所以这是不可能的.C#拥有它并充分利用它.C++不能这样做吗?
值和键都可以是自定义的用户定义类型或基本类型(整数,浮点数等).
存储用户定义的对象时,它们应该由shared_ptr引用.我正在使用Boost,所以这对于防止内存泄漏至关重要.其他三个平台要么是垃圾收集(C#/ Java),要么可以选择手动内存管理,引用计数和垃圾收集(目标C).Boost在实现引用计数方面做得很好,所以它应该是可能的.这正是Objective-C的NSDictionary在ARC开启的基础上制作的.
存储用户定义的对象时,默认情况下应根据内存地址对它们进行比较.非常重要:用户定义的对象不需要哈希函数,operator ==,operator <,公共基类等.需要这些东西可以明确地将比较从内存地址更改为其他内容,例如字符串的按值比较.但大多数时候我们只想要内存地址比较.
存储原始数据类型时,应按值进行比较.它们是否在某个内部对象中被包装/装箱应该与用户无关.再次,性能无关紧要.
使用if(dictionary [key])检查是否存在给定键的值.这不应该像在Boost和STL中那样插入默认的构造值对象.
应该为键和值强类型化.所以没有空虚*.此外,键和值都不需要公共基类,因为这会过于干扰并且会使第三方类更难以存储在地图中.
独特的钥匙.不允许空值(空值导致删除).
密钥应该可以作为向量或数组访问,并且可以通过索引进行遍历.迭代器需要太多输入.也就是说,我们应该能够写:
for(int i = 0; i <dictionary.getKeys().getCount(); i ++){shared_ptr value = dictionary [dictionary.getKeys()[i]]; }
必须编写充满迭代器声明的庞大for循环,这会使源代码的清晰度变得混乱.迭代器的typedef也不好,因为它们只会因为你遇到的每一个新的"Go To Definition"而增加复杂性,特别是在阅读别人的代码时.
我想我可以在列表中添加更多点数,但我会停在这里.您是否知道任何图书馆的地图类至少满足其中的大部分要点?我非常感谢任何建设性的反馈.
我在Java Collections教程中遇到过这个问题:
"还要注意,层次结构由两个不同的树组成 - 一个Map不是真正的集合."
这让我感到困惑,因为我一直以为地图是一个集合.任何人都可以对这意味着什么?
什么是"真实"的集合,为什么地图不是其中之一?
所以我有以下尝试映射地图列表,并且我试图获得"键"函数返回的键序列,只要我将它传递给单个映射.
(map #(keys %) ({:a-id 1 :b 3 :c 2} {:d-id 3 :e 9 :c 1} {:a-id 3 :d-id 5 :c 2}))
Run Code Online (Sandbox Code Playgroud)
这给我一个回复
java.lang.ClassCastException:null
我假设这与键上的返回类型是一个序列,并通过映射我猜它期望一个映射返回值??? 我真的不确定它为什么会这样做,我所知道的是,如果我能够在绘制我正在为我做的单一应用时为它做的事情,那将是方便的.
(keys {:a-id 1 :b 3 :c 2})
Run Code Online (Sandbox Code Playgroud)
这是 - (:a-id:b:c)
我有一个嵌套的地图,即map<int, map<int, string>>我想用初始化列表初始化.我可以使用初始化列表来初始化单级映射,但似乎无法找出嵌套映射的正确语法.它甚至可能吗?
MWE:
// This example shows how to initialize some maps
// Compile with this command:
// clang++ -std=c++11 -stdlib=libc++ map_initialization.cpp -o map_initialization
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main(){
cout << "\nLearning map initialization.\n" << endl;
map<int, string> level1map = {
{1, "a"},
{2, "b"},
{3, "c"}
};
for (auto& key_value : level1map) {
cout << "key: " << key_value.first << ", value=" << key_value.second << endl;
}
// This section …Run Code Online (Sandbox Code Playgroud) 我使用MultiMap的Guava库.我创建了一个示例MultiMap.当我打印地图的大小时,我得到4但实际值(我认为)应该是2.为什么这个差异?
import java.util.Collection;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
public class MultiMapTest {
public static void main(String... args) {
Multimap<String, String> myMultimap = ArrayListMultimap.create();
// Adding some key/value
myMultimap.put("Fruits", "Bannana");
myMultimap.put("Fruits", "Apple");
myMultimap.put("Fruits", "Pear");
myMultimap.put("Vegetables", "Carrot");
System.out.println(myMultimap);
// Getting the size
int size = myMultimap.size();
System.out.println(size); // 4
// Getting values
Collection<String> fruits = myMultimap.get("Fruits");
System.out.println(fruits); // [Bannana, Apple, Pear]
Collection<String> vegetables = myMultimap.get("Vegetables");
System.out.println(vegetables); // [Carrot]
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Fruits=[Bannana, Apple, Pear], Vegetables=[Carrot]}
4
[Bannana, …Run Code Online (Sandbox Code Playgroud) 我正在寻找一种合并地图的方法.每次我需要通过键合并地图时我都可以编写代码,但问题是对值的操作始终不同(对于字符串,int列表)
他们是这个问题的图书馆吗?
例如我的输入是:
//value is int - need to sum the values
val example1 = Map("a" -> 1 , "b" -> 1 , "c" -> 7)
val example2 = Map("a" -> 1 , "e" -> 5 , "f" -> 2)
//value is list - need to append
val example1 = Map("a" -> List(1) , "b" -> List(3) , "c" -> List(2))
val example2 = Map("a" -> List(4) , "e" -> List(1) , "f" -> List(1))
//value is string - nned …Run Code Online (Sandbox Code Playgroud) 做一些测试.我怀疑,哪个选项更好,使用a map或a for(基于性能,空间,时间等).
map(myfunction,xrange(n))
Run Code Online (Sandbox Code Playgroud)
要么
for element in xrange(n):
myfunction(element)
Run Code Online (Sandbox Code Playgroud)
谢谢.
我想将Id和Name存储到Java Collection中,如下所示:
121 Name_1
332 Name_9
334 Name_e
..........
Run Code Online (Sandbox Code Playgroud)
我可以使用a HashMap但我需要能够使用更多值扩展集合,如下所示:
121 Name_1 1
332 Name_9 1
334 Name_e 3
............
Run Code Online (Sandbox Code Playgroud)
是否有Java集合可以存储这些值而不使用Object?
当我使用operator []在c ++映射中插入元素时会发生错误.
我有这个地图<Pair,int>变量.当我向其中插入一个新元素,然后使用迭代器打印其键时,地图的某些元素会随机消失,并且值不会按递增顺序打印.但是,当我使用funtion insert()插入元素时,一切正常.我对operator []做错了什么?两种情况下结果不一样吗?
备注:每个密钥对是一个存储一对整数的结构.
这是一个例子:我插入以下六个键(5,9),(5,11),(5,12),(4,14),(1,10),(3,10).然后,我迭代地图,键(3,10)消失.此外,元素不按顺序打印.要查看应该打印的正确方法,请按照下面代码注释中的说明进行操作.
这是我的代码:
#include <iostream>
#include <map>
using namespace std;
struct Pair {
int a;
int b;
Pair(const int& a,const int& b) { //assures the first int is the smaller one
if (a < b) {
this->a = a;
this->b = b;
} else {
this->b = a;
this->a = b;
}
}
bool operator<(const Pair& otherPair) const {
return this->a < otherPair.a || this->b < otherPair.b;
}
};
int main() {
Pair elements …Run Code Online (Sandbox Code Playgroud) 我正在尝试在clojure返回笛卡尔积中编写函数
(my-compute-fn [1 2 3] [4 5 6])
Run Code Online (Sandbox Code Playgroud)
将返回
[[1 4] [1 5] [1 6] [2 4] [2 5] ....]
Run Code Online (Sandbox Code Playgroud)
我的尝试导致了这一点
(defn compute [col1 col2]
(let [totcol2 (count col2)
totcol1 (count col2)]
(map #(vector %1 %2)
(mapcat #(repeat totcol1 %1) col1)
(take (* totcol1 totcol2) (cycle col2)))))
Run Code Online (Sandbox Code Playgroud)
这项工作做得多,但看起来有点笨重.什么是更好,更简洁的实现,涉及clojure.core中更容易获得的函数?
谢谢!
编辑:发现了clojure组合,并没有一个神奇的功能方式来做到这一点.