te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>dictionary - Javascript map with composite keys - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

dictionary - Javascript map with composite keys - Stack Overflow

programmeradmin3浏览0评论

In JavaScript I want to store values to pound keys, similar to a C# dictionary with a tuple as key. This is where I came across the Map class. However, it does not seem to work quite as well as I would like it to. Here's my current approach:

var test = new Map();

test.set({a: 1, b: 1}, 'Bla');
test.set({a: 5, b: 7}, 'Blub');

test.get({a: 1, b: 1}); // ==> Returns undefined; would expect 'Bla'

I guess, that this has something to do that both objects with {a: 1, b: 1} have a different memory address and therefore are the same, but not identical. The Dictionary class in c# uses a hash function in background. Is there something similar in JS? Or a much easier approach?

My real key object consistst of three strings.

In JavaScript I want to store values to pound keys, similar to a C# dictionary with a tuple as key. This is where I came across the Map class. However, it does not seem to work quite as well as I would like it to. Here's my current approach:

var test = new Map();

test.set({a: 1, b: 1}, 'Bla');
test.set({a: 5, b: 7}, 'Blub');

test.get({a: 1, b: 1}); // ==> Returns undefined; would expect 'Bla'

I guess, that this has something to do that both objects with {a: 1, b: 1} have a different memory address and therefore are the same, but not identical. The Dictionary class in c# uses a hash function in background. Is there something similar in JS? Or a much easier approach?

My real key object consistst of three strings.

Share Improve this question edited Apr 15, 2020 at 14:36 André Reichelt asked Apr 15, 2020 at 14:32 André ReicheltAndré Reichelt 1,6311 gold badge22 silver badges59 bronze badges 5
  • Your analysis is right: Map uses reference equality on the keys and not value equality. If your objects just have three fixed strings, can you synthesize a key for map by bining them? E.g. makeKey = (({s1, s2, s3}) => `${s1}~${s2}~${s3}`? Then test.set(makeKey({a: 1, b: 1}), 'Bla') ... test.get(makeKey({a: 1, b: 1}) – Scott Sauyet Commented Apr 15, 2020 at 14:35
  • Sure, that would work. Would you rather use the Map class or a simple object in that case? – André Reichelt Commented Apr 15, 2020 at 14:37
  • 2 Either one would be fine. To my mind, this restriction on Map makes it much less useful than it could be. – Scott Sauyet Commented Apr 15, 2020 at 14:38
  • @ScottSauyet If you want, you can post your idea as an answer. – André Reichelt Commented Apr 15, 2020 at 14:53
  • 1 Nah, simple enough to be just a ment. Besides, the JSON.stringify ment from Captain Mhmdrz_A is most likely a better idea. – Scott Sauyet Commented Apr 15, 2020 at 15:29
Add a ment  | 

2 Answers 2

Reset to default 6

Your analysis is correct. It works like this because in Javascript you usually operate primitive objects that don't have all this hashing behavior attached to them out of the box. Nothing stops you from implementing your own Dictionary with hash function in background though

class Dictionary {
  map = {}

  constructor(hashFunction) {
    this.hashFunction = hashFunction
  }

  set(key, item) {
    this.map[this.hashFunction(key)] = item
  }

  get(key) {
    return this.map[this.hashFunction(key)]
  }

  delete(key) {
    delete this.map[this.hashFunction(key)]
  }
}

const dict = new Dictionary((keyObject) => JSON.stringify(keyObject))
dict.set({ a: 1, b: 2 }, 'hello')
console.log(dict.get({ a: 1, b: 2 })) // hello

As to what to use, Map or object, the difference between Map and object is simply that object only supports string keys (also Symbols but irrelevant right now) while Map supports any value at a cost of using more resources, less patibility with old browsers, and it's generally less handy to use than object (and also stops GC from cleaning out those objects you use as keys). That said, object is your choice here

{} this operator will create a new object every time; and a new object will have a different object refenece each time; if you save the object reference and use that for multiple operation its ok; but since you are trying to use a new object refence every time it won't work; you may either use a primitive type as key, or same object reference like the snippet below

//approach 1 using same object reference
var test = new Map();
var obj = {a: 1, b: 1};
test.set(obj, 'Bla');
test.set({a: 5, b: 7}, 'Blub');
let result = test.get(obj); 
console.log(result);

// aproach 2 using JSON.stringify
test = new Map();
test.set(JSON.stringify({a: 1, b: 1}), 'Bla');
test.set({a: 5, b: 7}, 'Blub');
result = test.get(JSON.stringify({a: 1, b: 1})); 
console.log(result)

发布评论

评论列表(0)

  1. 暂无评论