lodash/underscore 计算数组中非唯一元素的数量
lodash/underscore find the number of non-unique elements in an array
我有一个包含一些字符串的数组,我需要找出有多少字符串不是唯一的 - _.uniq 相反。我已经尝试了一些事情,但到目前为止都遇到了死胡同。我觉得答案很简单。举个例子:
["abc", "abc", "def", "rty", "rty", "rty", "uig", "ghe", "bed", "abc"]
我想从中得到答案 2,因为数组中只有两个字符串不止一次出现。
这是 underscore
的一种方法。您只需继续在累加器上搜索重复值并将非唯一项添加到另一个 object/array。注意:这仅适用于字符串数组。
var list = ["eyxCyqqbn3", "jPEbM00mvQ", "5pi7wTh689", "P2iBGGwuWZ", "eyxCyqqbn3", "jPEbM00mvQ", "uX1GrD4UQt", "uX1GrD4UQt", "uX1GrD4UQt", "uX1GrD4UQt", "uX1GrD4UQt", "yXkmkZo0lW", "5pi7wTh689", "P2iBGGwuWZ", "uX1GrD4UQt", '__proto__', '__proto__'];
var repeated = Object.create(null);
_.reduce(list, function(acc, val) {
if (Object.prototype.hasOwnProperty.call(acc, val)) {
if (!Object.prototype.hasOwnProperty.call(repeated, val)) {
repeated[val] = true;
}
}
acc[val] = true;
return acc;
}, Object.create(null));
var amountrepeated = Object.keys(repeated).length;
document.getElementById('results').innerHTML = amountrepeated;
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<pre id="results"></pre>
var list = ["abc", "abc", "def", "rty", "rty", "rty", "uig", "ghe", "bed", "abc"];
var repeatedCount = _.filter(_.groupBy(list), function(n) { return n.length > 1; }).length;
所以您正在寻找一种廉价的跨浏览器解决方案来解决您的问题?通过使用专为 ES3+ 设计的下划线或 lodash。但是,您必须小心列表中的字符串。
我们来看看MinusFour的回答
var $countOfLikeStrings3 = function(arrayOfStrings) {
var repeated = {
length: 0
};
_.reduce(arrayOfStrings, function(acc, val) {
if (acc[val] !== undefined) {
if (repeated[val] === undefined) {
repeated[val] = true;
repeated.length++;
}
}
acc[val] = true;
return acc;
}, {});
return repeated.length;
}
var pre = document.getElementById('out');
function log(result) {
pre.appendChild(document.createTextNode(result + '\n'));
}
var list1 = ['length', 'length', 'constructor', 'constructor', 'prototype', 'prototype', '__proto__', '__proto__'];
log($countOfLikeStrings3(list1));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<pre id="out"></pre>
我猜我们没想到结果是 1?
一个现在的阿奎那解决方案。
var $countOfLikeStrings2 = function(arrayOfStrings) {
return _.filter(_.groupBy(arrayOfStrings), function(n) {
return n.length > 1;
}).length;
}
var pre = document.getElementById('out');
function log(result) {
pre.appendChild(document.createTextNode(result + '\n'));
}
var list1 = ['length', 'length', 'constructor', 'constructor', 'prototype', 'prototype', '__proto__', '__proto__'];
log($countOfLikeStrings2(list1));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<pre id="out"></pre>
再说一遍,没想到是 3?
好的,现在让我们使用一些现代的 ES6,这样浏览器支持会减少,但这将适用于当前的主流浏览器和节点。
var $countOfLikeStrings1 = (function(create) {
'use strict';
var symRepeated = Symbol('repeated'),
symLength = Symbol('length');
return function(arrayOfStrings) {
var accumulator = create(null);
accumulator[symRepeated] = create(null);
accumulator[symRepeated][symLength] = 0;
return arrayOfStrings.reduce(function(acc, stringItem) {
var repeated = acc[symRepeated],
count = (acc[stringItem] || 0) + 1;
acc[stringItem] = count;
if (count > 1) {
if (!repeated[stringItem]) {
repeated[symLength] += 1;
}
repeated[stringItem] = count;
}
return acc;
}, accumulator)[symRepeated][symLength];
};
}(Object.create));
var pre = document.getElementById('out');
function log(result) {
pre.appendChild(document.createTextNode(result + '\n'));
}
var list1 = ['length', 'length', 'constructor', 'constructor', 'prototype', 'prototype', '__proto__', '__proto__'];
log($countOfLikeStrings1(list1));
<pre id="out"></pre>
嘿!差不多了,4!
所以,在 ES6 中甚至可能有更好的方法——我仍在学习新的东西。并且通过一些额外的 ES3 和 ES5 代码,其他两个解决方案也可以得到改进。
抛开这些问题,这里是 jsPerf 这 3 个解决方案的原样。
更新:重新设计为更加 ES6
function $countOfLikeStrings4(arrayOfStrings) {
'use strict';
const accumulator = new Map(),
repeated = new Map();
var oldCount,
newCount;
for (let stringItem of arrayOfStrings) {
oldCount = accumulator.get(stringItem) || 0;
newCount = oldCount + 1;
accumulator.set(stringItem, newCount);
if (newCount > 1 && !repeated.has(stringItem)) {
repeated.set(stringItem, true);
}
}
return repeated.size;
}
var pre = document.getElementById('out');
function log(result) {
pre.appendChild(document.createTextNode(result + '\n'));
}
var list1 = ['length', 'length', 'constructor', 'constructor', 'prototype', 'prototype', '__proto__', '__proto__'];
log($countOfLikeStrings4(list1));
<pre id="out"></pre>
我有一个包含一些字符串的数组,我需要找出有多少字符串不是唯一的 - _.uniq 相反。我已经尝试了一些事情,但到目前为止都遇到了死胡同。我觉得答案很简单。举个例子:
["abc", "abc", "def", "rty", "rty", "rty", "uig", "ghe", "bed", "abc"]
我想从中得到答案 2,因为数组中只有两个字符串不止一次出现。
这是 underscore
的一种方法。您只需继续在累加器上搜索重复值并将非唯一项添加到另一个 object/array。注意:这仅适用于字符串数组。
var list = ["eyxCyqqbn3", "jPEbM00mvQ", "5pi7wTh689", "P2iBGGwuWZ", "eyxCyqqbn3", "jPEbM00mvQ", "uX1GrD4UQt", "uX1GrD4UQt", "uX1GrD4UQt", "uX1GrD4UQt", "uX1GrD4UQt", "yXkmkZo0lW", "5pi7wTh689", "P2iBGGwuWZ", "uX1GrD4UQt", '__proto__', '__proto__'];
var repeated = Object.create(null);
_.reduce(list, function(acc, val) {
if (Object.prototype.hasOwnProperty.call(acc, val)) {
if (!Object.prototype.hasOwnProperty.call(repeated, val)) {
repeated[val] = true;
}
}
acc[val] = true;
return acc;
}, Object.create(null));
var amountrepeated = Object.keys(repeated).length;
document.getElementById('results').innerHTML = amountrepeated;
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<pre id="results"></pre>
var list = ["abc", "abc", "def", "rty", "rty", "rty", "uig", "ghe", "bed", "abc"];
var repeatedCount = _.filter(_.groupBy(list), function(n) { return n.length > 1; }).length;
所以您正在寻找一种廉价的跨浏览器解决方案来解决您的问题?通过使用专为 ES3+ 设计的下划线或 lodash。但是,您必须小心列表中的字符串。
我们来看看MinusFour的回答
var $countOfLikeStrings3 = function(arrayOfStrings) {
var repeated = {
length: 0
};
_.reduce(arrayOfStrings, function(acc, val) {
if (acc[val] !== undefined) {
if (repeated[val] === undefined) {
repeated[val] = true;
repeated.length++;
}
}
acc[val] = true;
return acc;
}, {});
return repeated.length;
}
var pre = document.getElementById('out');
function log(result) {
pre.appendChild(document.createTextNode(result + '\n'));
}
var list1 = ['length', 'length', 'constructor', 'constructor', 'prototype', 'prototype', '__proto__', '__proto__'];
log($countOfLikeStrings3(list1));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<pre id="out"></pre>
我猜我们没想到结果是 1?
一个现在的阿奎那解决方案。
var $countOfLikeStrings2 = function(arrayOfStrings) {
return _.filter(_.groupBy(arrayOfStrings), function(n) {
return n.length > 1;
}).length;
}
var pre = document.getElementById('out');
function log(result) {
pre.appendChild(document.createTextNode(result + '\n'));
}
var list1 = ['length', 'length', 'constructor', 'constructor', 'prototype', 'prototype', '__proto__', '__proto__'];
log($countOfLikeStrings2(list1));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script>
<pre id="out"></pre>
再说一遍,没想到是 3?
好的,现在让我们使用一些现代的 ES6,这样浏览器支持会减少,但这将适用于当前的主流浏览器和节点。
var $countOfLikeStrings1 = (function(create) {
'use strict';
var symRepeated = Symbol('repeated'),
symLength = Symbol('length');
return function(arrayOfStrings) {
var accumulator = create(null);
accumulator[symRepeated] = create(null);
accumulator[symRepeated][symLength] = 0;
return arrayOfStrings.reduce(function(acc, stringItem) {
var repeated = acc[symRepeated],
count = (acc[stringItem] || 0) + 1;
acc[stringItem] = count;
if (count > 1) {
if (!repeated[stringItem]) {
repeated[symLength] += 1;
}
repeated[stringItem] = count;
}
return acc;
}, accumulator)[symRepeated][symLength];
};
}(Object.create));
var pre = document.getElementById('out');
function log(result) {
pre.appendChild(document.createTextNode(result + '\n'));
}
var list1 = ['length', 'length', 'constructor', 'constructor', 'prototype', 'prototype', '__proto__', '__proto__'];
log($countOfLikeStrings1(list1));
<pre id="out"></pre>
嘿!差不多了,4!
所以,在 ES6 中甚至可能有更好的方法——我仍在学习新的东西。并且通过一些额外的 ES3 和 ES5 代码,其他两个解决方案也可以得到改进。
抛开这些问题,这里是 jsPerf 这 3 个解决方案的原样。
更新:重新设计为更加 ES6
function $countOfLikeStrings4(arrayOfStrings) {
'use strict';
const accumulator = new Map(),
repeated = new Map();
var oldCount,
newCount;
for (let stringItem of arrayOfStrings) {
oldCount = accumulator.get(stringItem) || 0;
newCount = oldCount + 1;
accumulator.set(stringItem, newCount);
if (newCount > 1 && !repeated.has(stringItem)) {
repeated.set(stringItem, true);
}
}
return repeated.size;
}
var pre = document.getElementById('out');
function log(result) {
pre.appendChild(document.createTextNode(result + '\n'));
}
var list1 = ['length', 'length', 'constructor', 'constructor', 'prototype', 'prototype', '__proto__', '__proto__'];
log($countOfLikeStrings4(list1));
<pre id="out"></pre>