This commit is contained in:
darenhsu
2022-07-17 13:16:16 +08:00
parent 84759556ff
commit befd344ab0
28070 changed files with 4008428 additions and 1 deletions
+41
View File
@@ -0,0 +1,41 @@
{
"passfail" : false,
"maxerr" : 20,
"browser" : false,
"node" : true,
"debug" : false,
"devel" : true,
"es5" : false,
"strict" : false,
"globalstrict" : false,
"asi" : false,
"laxbreak" : false,
"bitwise" : false,
"boss" : true,
"curly" : false,
"eqeqeq" : false,
"eqnull" : false,
"evil" : true,
"expr" : true,
"forin" : false,
"immed" : true,
"latedef" : false,
"loopfunc" : true,
"noarg" : true,
"regexp" : true,
"regexdash" : false,
"scripturl" : true,
"shadow" : true,
"supernew" : false,
"undef" : false,
"newcap" : false,
"proto" : true,
"noempty" : true,
"nonew" : false,
"nomen" : false,
"onevar" : false,
"plusplus" : false,
"sub" : false,
"trailing" : false,
"white" : false
}
+6
View File
@@ -0,0 +1,6 @@
language: node_js
node_js:
- "0.10"
- "0.11"
script: npm run test
+136
View File
@@ -0,0 +1,136 @@
# Multimap - Map which Allow Multiple Values for the same Key
[![NPM version](https://badge.fury.io/js/multimap.svg)](http://badge.fury.io/js/multimap)
[![Build Status](https://travis-ci.org/villadora/multi-map.png?branch=master)](https://travis-ci.org/villadora/multi-map)
## Install
```bash
npm install multimap --save
```
## Usage
If you'd like to use native version when it exists and fallback to polyfill if it doesn't, but without implementing `Map` on global scope, do:
```javascript
var Multimap = require('multimap');
var m = new Multimap();
```
If the global es6 `Map` exists or `Multimap.Map` is set, `Multimap` will use the `Map` as inner store, that means Object can be used as key.
```javascript
var Multimap = require('multimap');
// if harmony is on
/* nothing need to do */
// or if you are using es6-shim
Multimap.Map = ShimMap;
var m = new Multimap();
var key = {};
m.set(key, 'one');
```
Otherwise, an object will be used, all the keys will be transformed into string.
### In Modern Browser
Just download the `index.js` as `Multimap.js`.
```
<script src=Multimap.js"></script>
<script>
var map = new Multimap([['a', 1], ['b', 2], ['c', 3]]);
map = map.set('b', 20);
map.get('b'); // [2, 20]
</script>
```
Or use as an AMD loader:
```
require(['./Multimap.js'], function (Multimap) {
var map = new Multimap([['a', 1], ['b', 2], ['c', 3]]);
map = map.set('b', 20);
map.get('b'); // [2, 20]
});
```
* Browsers should support `Object.defineProperty` and `Array.prototype.forEach`.
## API
Following shows how to use `Multimap`:
```javascript
var Multimap = require('multimap');
var map = new Multimap([['a', 'one'], ['b', 1], ['a', 'two'], ['b', 2]]);
map.size; // 4
map.count; // 2
map.get('a'); // ['one', 'two']
map.get('b'); // [1, 2]
map.has('a'); // true
map.has('foo'); // false
map.has('a', 'one'); // true
map.has('b', 3); // false
map.set('a', 'three');
map.size; // 5
map.count; // 2
map.get('a'); // ['one', 'two', 'three']
map.set('b', 3, 4);
map.size; // 7
map.count; // 2
map.delete('a', 'three'); // true
map.delete('x'); // false
map.delete('a', 'four'); // false
map.delete('b'); // true
map.size; // 2
map.count; // 1
map.set('b', 1, 2);
map.size; // 4
map.count; // 2
map.forEach(function (value, key) {
// iterates { 'one', 'a' }, { 'two', 'a' }, { 1, b }, { 2, 'b' }
});
map.forEachEntry(function (entry, key) {
// iterates {['one', 'two'], 'a' }, {[1, 2], 'b' }
});
var keys = map.keys(); // iterator with ['a', 'b']
keys.next().value; // 'a'
var values = map.values(); // iterator ['one', 'two', 1, 2]
map.clear(); // undefined
map.size; // 0
map.count; // 0
```
## License
(The MIT License)
Copyright (c) 2013, Villa.Gao <jky239@gmail.com>;
All rights reserved.
+226
View File
@@ -0,0 +1,226 @@
"use strict";
/* global module, define */
function mapEach(map, operation){
var keys = map.keys();
var next;
while(!(next = keys.next()).done) {
operation(map.get(next.value), next.value, map);
}
}
var Multimap = (function() {
var mapCtor;
if (typeof Map !== 'undefined') {
mapCtor = Map;
if (!Map.prototype.keys) {
Map.prototype.keys = function() {
var keys = [];
this.forEach(function(item, key) {
keys.push(key);
});
return keys;
};
}
}
function Multimap(iterable) {
var self = this;
self._map = mapCtor;
if (Multimap.Map) {
self._map = Multimap.Map;
}
self._ = self._map ? new self._map() : {};
if (iterable) {
iterable.forEach(function(i) {
self.set(i[0], i[1]);
});
}
}
/**
* @param {Object} key
* @return {Array} An array of values, undefined if no such a key;
*/
Multimap.prototype.get = function(key) {
return this._map ? this._.get(key) : this._[key];
};
/**
* @param {Object} key
* @param {Object} val...
*/
Multimap.prototype.set = function(key, val) {
var args = Array.prototype.slice.call(arguments);
key = args.shift();
var entry = this.get(key);
if (!entry) {
entry = [];
if (this._map)
this._.set(key, entry);
else
this._[key] = entry;
}
Array.prototype.push.apply(entry, args);
return this;
};
/**
* @param {Object} key
* @param {Object=} val
* @return {boolean} true if any thing changed
*/
Multimap.prototype.delete = function(key, val) {
if (!this.has(key))
return false;
if (arguments.length == 1) {
this._map ? (this._.delete(key)) : (delete this._[key]);
return true;
} else {
var entry = this.get(key);
var idx = entry.indexOf(val);
if (idx != -1) {
entry.splice(idx, 1);
return true;
}
}
return false;
};
/**
* @param {Object} key
* @param {Object=} val
* @return {boolean} whether the map contains 'key' or 'key=>val' pair
*/
Multimap.prototype.has = function(key, val) {
var hasKey = this._map ? this._.has(key) : this._.hasOwnProperty(key);
if (arguments.length == 1 || !hasKey)
return hasKey;
var entry = this.get(key) || [];
return entry.indexOf(val) != -1;
};
/**
* @return {Array} all the keys in the map
*/
Multimap.prototype.keys = function() {
if (this._map)
return makeIterator(this._.keys());
return makeIterator(Object.keys(this._));
};
/**
* @return {Array} all the values in the map
*/
Multimap.prototype.values = function() {
var vals = [];
this.forEachEntry(function(entry) {
Array.prototype.push.apply(vals, entry);
});
return makeIterator(vals);
};
/**
*
*/
Multimap.prototype.forEachEntry = function(iter) {
mapEach(this, iter);
};
Multimap.prototype.forEach = function(iter) {
var self = this;
self.forEachEntry(function(entry, key) {
entry.forEach(function(item) {
iter(item, key, self);
});
});
};
Multimap.prototype.clear = function() {
if (this._map) {
this._.clear();
} else {
this._ = {};
}
};
Object.defineProperty(
Multimap.prototype,
"size", {
configurable: false,
enumerable: true,
get: function() {
var total = 0;
mapEach(this, function(value){
total += value.length;
});
return total;
}
});
Object.defineProperty(
Multimap.prototype,
"count", {
configurable: false,
enumerable: true,
get: function() {
return this._.size;
}
});
var safariNext;
try{
safariNext = new Function('iterator', 'makeIterator', 'var keysArray = []; for(var key of iterator){keysArray.push(key);} return makeIterator(keysArray).next;');
}catch(error){
// for of not implemented;
}
function makeIterator(iterator){
if(Array.isArray(iterator)){
var nextIndex = 0;
return {
next: function(){
return nextIndex < iterator.length ?
{value: iterator[nextIndex++], done: false} :
{done: true};
}
};
}
// Only an issue in safari
if(!iterator.next && safariNext){
iterator.next = safariNext(iterator, makeIterator);
}
return iterator;
}
return Multimap;
})();
if(typeof exports === 'object' && module && module.exports)
module.exports = Multimap;
else if(typeof define === 'function' && define.amd)
define(function() { return Multimap; });
+63
View File
@@ -0,0 +1,63 @@
{
"_args": [
[
"multimap@1.1.0",
"/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series"
]
],
"_development": true,
"_from": "multimap@1.1.0",
"_id": "multimap@1.1.0",
"_inBundle": false,
"_integrity": "sha512-0ZIR9PasPxGXmRsEF8jsDzndzHDj7tIav+JUmvIFB/WHswliFnquxECT/De7GR4yg99ky/NlRKJT82G1y271bw==",
"_location": "/multimap",
"_phantomChildren": {},
"_requested": {
"type": "version",
"registry": true,
"raw": "multimap@1.1.0",
"name": "multimap",
"escapedName": "multimap",
"rawSpec": "1.1.0",
"saveSpec": null,
"fetchSpec": "1.1.0"
},
"_requiredBy": [
"/eslint-template-visitor"
],
"_resolved": "https://registry.npmjs.org/multimap/-/multimap-1.1.0.tgz",
"_spec": "1.1.0",
"_where": "/mnt/Foxconn/Digitalent/Deverloper/liff-push_2series",
"author": {
"name": "villa.gao",
"email": "jky239@gmail.com"
},
"bugs": {
"url": "https://github.com/villadora/multi-map/issues"
},
"dependencies": {},
"description": "multi-map which allow multiple values for the same key",
"devDependencies": {
"chai": "~1.7.2",
"es6-shim": "^0.13.0",
"jshint": "~2.1.9"
},
"homepage": "https://github.com/villadora/multi-map#readme",
"keywords": [
"keys",
"map",
"multiple"
],
"license": "MIT",
"main": "index.js",
"name": "multimap",
"repository": {
"type": "git",
"url": "git://github.com/villadora/multi-map.git"
},
"scripts": {
"lint": "jshint *.js test/*.js",
"test": "npm run lint; node test/index.js;node test/es6map.js"
},
"version": "1.1.0"
}
+86
View File
@@ -0,0 +1,86 @@
"use strict";
var assert = require('chai').assert;
require('es6-shim');
var Multimap = require('..');
var map = new Multimap([
['a', 'one'],
['b', 1],
['a', 'two'],
['b', 2]
]);
assert.equal(map.size, 4);
assert.equal(map.get('a').length, 2);
assert.equal(map.get('a')[0], 'one'); // ['one', 'two']
assert.equal(map.get('a')[1], 'two'); // ['one', 'two']
assert.equal(map.get('b').length, 2);
assert.equal(map.get('b')[0], 1); // [1, 2]
assert.equal(map.get('b')[1], 2); // [1, 2]
assert(map.has('a'), "map contains key 'a'");
assert(!map.has('foo'), "map does not contain key 'foo'");
assert(map.has('a', 'one'), "map contains entry 'a'=>'one'");
assert(!map.has('b', 3), "map does not contain entry 'b'=>3");
map.set('a', 'three');
assert.equal(map.size, 5);
assert.equal(map.get('a').length, 3); // ['one', 'two', 'three']
map.set('b', 3, 4);
assert.equal(map.size, 7);
assert(map.delete('a', 'three'), "delete 'a'=>'three'");
assert.equal(map.size, 6);
assert(!map.delete('x'), "empty 'x' for delete");
assert(!map.delete('a', 'four'), "no such entry 'a'=>'four'");
assert(map.delete('b'), "delete all 'b'");
assert.equal(map.size, 2);
map.set('b', 1, 2);
assert.equal(map.size, 4); // 4
var cnt = 0;
map.forEach(function(value, key) {
// iterates { 'a', 'one' }, { 'a', 'two' }, { 'b', 1 }, { 'b', 2 }
cnt++;
assert(key == 'a' || key == 'b', "key must be either 'a' or 'b'");
});
assert.equal(cnt, 4);
cnt = 0;
map.forEachEntry(function(entry, key) {
// iterates { 'a', ['one', 'two'] }, { 'b', [1, 2] }
cnt++;
assert(key == 'a' || key == 'b', "key must be either 'a' or 'b'");
assert.equal(entry.length, 2);
});
assert.equal(cnt, 2);
var keys = map.keys(); // ['a', 'b']
assert.equal(keys.next().value, 'a');
assert.equal(keys.next().value, 'b');
assert(keys.next().done);
var values = map.values(); // ['one', 'two', 1, 2]
assert.equal(values.next().value, 'one');
assert.equal(values.next().value, 'two');
assert.equal(values.next().value, 1);
assert.equal(values.next().value, 2);
assert(values.next().done);
map.clear();
assert.equal(map.size, 0);
+91
View File
@@ -0,0 +1,91 @@
"use strict";
var assert = require('chai').assert;
var Multimap = require('..');
var map = new Multimap([
['a', 'one'],
['b', 1],
['a', 'two'],
['b', 2]
]);
assert.equal(map.size, 4);
assert.equal(map.count, 2);
assert.equal(map.get('a').length, 2);
assert.equal(map.get('a')[0], 'one'); // ['one', 'two']
assert.equal(map.get('a')[1], 'two'); // ['one', 'two']
assert.equal(map.get('b').length, 2);
assert.equal(map.get('b')[0], 1); // [1, 2]
assert.equal(map.get('b')[1], 2); // [1, 2]
assert(map.has('a'), "map contains key 'a'");
assert(!map.has('foo'), "map does not contain key 'foo'");
assert(map.has('a', 'one'), "map contains entry 'a'=>'one'");
assert(!map.has('b', 3), "map does not contain entry 'b'=>3");
map.set('a', 'three');
assert.equal(map.size, 5);
assert.equal(map.count, 2);
assert.equal(map.get('a').length, 3); // ['one', 'two', 'three']
map.set('b', 3, 4);
assert.equal(map.size, 7);
assert.equal(map.count, 2);
assert(map.delete('a', 'three'), "delete 'a'=>'three'");
assert.equal(map.size, 6);
assert.equal(map.count, 2);
assert(!map.delete('x'), "empty 'x' for delete");
assert(!map.delete('a', 'four'), "no such entry 'a'=>'four'");
assert(map.delete('b'), "delete all 'b'");
assert.equal(map.size, 2);
assert.equal(map.count, 1);
map.set('b', 1, 2);
assert.equal(map.size, 4); // 4
assert.equal(map.count, 2);
var cnt = 0;
map.forEach(function(value, key) {
// iterates { 'a', 'one' }, { 'a', 'two' }, { 'b', 1 }, { 'b', 2 }
cnt++;
assert(key == 'a' || key == 'b', "key must be either 'a' or 'b'");
});
assert.equal(cnt, 4);
cnt = 0;
map.forEachEntry(function(entry, key) {
// iterates { 'a', ['one', 'two'] }, { 'b', [1, 2] }
cnt++;
assert(key == 'a' || key == 'b', "key must be either 'a' or 'b'");
assert.equal(entry.length, 2);
});
assert.equal(cnt, 2);
var keys = map.keys(); // ['a', 'b']
assert.equal(keys.next().value, 'a');
assert.equal(keys.next().value, 'b');
assert(keys.next().done);
var values = map.values(); // ['one', 'two', 1, 2]
assert.equal(values.next().value, 'one');
assert.equal(values.next().value, 'two');
assert.equal(values.next().value, 1);
assert.equal(values.next().value, 2);
assert(values.next().done);
map.clear();
assert.equal(map.size, 0);
assert.equal(map.count, 0);
+92
View File
@@ -0,0 +1,92 @@
<html>
<head>
<title>MultiMap Tests</title>
<script src="../node_modules/chai/chai.js"></script>
<script src="../index.js"></script>
<script type="text/javascript">
var assert = chai.assert;
var map = new Multimap([
['a', 'one'],
['b', 1],
['a', 'two'],
['b', 2]
]);
assert.equal(map.size, 4);
assert.equal(map.get('a').length, 2);
assert.equal(map.get('a')[0], 'one'); // ['one', 'two']
assert.equal(map.get('a')[1], 'two'); // ['one', 'two']
assert.equal(map.get('b').length, 2);
assert.equal(map.get('b')[0], 1); // [1, 2]
assert.equal(map.get('b')[1], 2); // [1, 2]
assert(map.has('a'), "map contains key 'a'");
assert(!map.has('foo'), "map does not contain key 'foo'");
assert(map.has('a', 'one'), "map contains entry 'a'=>'one'");
assert(!map.has('b', 3), "map does not contain entry 'b'=>3");
map.set('a', 'three');
assert.equal(map.size, 5);
assert.equal(map.get('a').length, 3); // ['one', 'two', 'three']
map.set('b', 3, 4);
assert.equal(map.size, 7);
assert(map.delete('a', 'three'), "delete 'a'=>'three'");
assert.equal(map.size, 6);
assert(!map.delete('x'), "empty 'x' for delete");
assert(!map.delete('a', 'four'), "no such entry 'a'=>'four'");
assert(map.delete('b'), "delete all 'b'");
assert.equal(map.size, 2);
map.set('b', 1, 2);
assert.equal(map.size, 4); // 4
var cnt = 0;
map.forEach(function(value, key) {
// iterates { 'a', 'one' }, { 'a', 'two' }, { 'b', 1 }, { 'b', 2 }
cnt++;
assert(key == 'a' || key == 'b', "key must be either 'a' or 'b'");
});
assert.equal(cnt, 4);
cnt = 0;
map.forEachEntry(function(entry, key) {
// iterates { 'a', ['one', 'two'] }, { 'b', [1, 2] }
cnt++;
assert(key == 'a' || key == 'b', "key must be either 'a' or 'b'");
assert.equal(entry.length, 2);
});
assert.equal(cnt, 2);
var keys = map.keys(); // ['a', 'b']
assert.equal(keys.next().value, 'a');
assert.equal(keys.next().value, 'b');
assert(keys.next().done);
var values = map.values(); // ['one', 'two', 1, 2]
assert.equal(values.next().value, 'one');
assert.equal(values.next().value, 'two');
assert.equal(values.next().value, 1);
assert.equal(values.next().value, 2);
assert(values.next().done);
map.clear();
assert.equal(map.size, 0);
</script>
</head>
<body>
</body>
</html>