我有一个包含一定数量字符串的数组,我需要找出有多少字符串不唯一 - 与_.uniq相反。我已经尝试了一些事情,但到目前为止已经提出了死胡同。我觉得答案很简单。举个例子:
/**
* @var \Doctrine\Common\Collections\Collection
* @ORM\ManyToMany(targetEntity="Application\Entity\Role")
* @ORM\JoinTable(name="user_role_linker",
* joinColumns={@ORM\JoinColumn(name="user_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="role_id", referencedColumnName="id")}
* )
*/
protected $roles;
我想从这里得到2的答案,因为只有两个字符串在数组中不止一次。
答案 0 :(得分:5)
var list = ["abc", "abc", "def", "rty", "rty", "rty", "uig", "ghe", "bed", "abc"];
var repeatedCount = _.filter(_.groupBy(list), function(n) { return n.length > 1; }).length;
答案 1 :(得分:2)
所以,您正在寻找一种廉价的跨浏览器解决方案来解决您的问题?通过使用为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的结果?
现在的aquinas解决方案。
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。
更新:重新设计为更多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>
答案 2 :(得分:1)
这是使用underscore
执行此操作的一种方法。您只需继续在累加器上搜索重复值,并将非唯一项添加到另一个对象/数组。注意:这仅适用于字符串数组。
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;
&#13;
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<pre id="results"></pre>
&#13;