JavaScript 배열에서 가장 많이 발생하는 요소 ( mode ) 를 결정하는 우아한 방법을 찾고 있습니다.
예를 들어
['pear', 'apple', 'orange', 'apple']
'apple'
요소는 가장 자주 하나이다.
JavaScript 배열에서 가장 많이 발생하는 요소 ( mode ) 를 결정하는 우아한 방법을 찾고 있습니다.
예를 들어
['pear', 'apple', 'orange', 'apple']
'apple'
요소는 가장 자주 하나이다.
답변:
이것은 단지 모드입니다. 다음은 빠르고 최적화되지 않은 솔루션입니다. O (n)이어야합니다.
function mode(array)
{
if(array.length == 0)
return null;
var modeMap = {};
var maxEl = array[0], maxCount = 1;
for(var i = 0; i < array.length; i++)
{
var el = array[i];
if(modeMap[el] == null)
modeMap[el] = 1;
else
modeMap[el]++;
if(modeMap[el] > maxCount)
{
maxEl = el;
maxCount = modeMap[el];
}
}
return maxEl;
}
2009 년부터 자바 스크립트에서 몇 가지 개발이있었습니다. 다른 옵션을 추가 할 것이라고 생각했습니다. 나는 그것이 실제로 문제가 될 때까지 효율성에 덜 관심을 가지고 있으므로 "우아한" 코드 (OP에 의해 규정 된대로)에 대한 나의 정의는 가독성을 선호합니다-물론 주관적입니다 ...
function mode(arr){
return arr.sort((a,b) =>
arr.filter(v => v===a).length
- arr.filter(v => v===b).length
).pop();
}
mode(['pear', 'apple', 'orange', 'apple']); // apple
이 특정 예에서 집합의 두 개 이상의 요소가 동일한 발생을 갖는 경우 배열에서 가장 최근에 나타나는 요소가 반환됩니다. 또한 원래 배열을 수정한다는 점을 지적 할 가치가 있습니다 Array.slice
. 사전 에 전화로 원할 경우 방지 할 수 있습니다 .
편집 : 2015 년 이 발생 했기 때문에 일부 ES6 뚱뚱한 화살표로 예제를 업데이트했으며 예쁘게 보입니다 ... 이전 버전과의 호환성이 걱정된다면 개정 내역 에서 찾을 수 있습니다 .
George Jempty's
알고리즘 계정에 대한 요청에 따라 수정 된 버전의 Matthew Flaschen's
알고리즘을 제안합니다 .
function modeString(array) {
if (array.length == 0) return null;
var modeMap = {},
maxEl = array[0],
maxCount = 1;
for (var i = 0; i < array.length; i++) {
var el = array[i];
if (modeMap[el] == null) modeMap[el] = 1;
else modeMap[el]++;
if (modeMap[el] > maxCount) {
maxEl = el;
maxCount = modeMap[el];
} else if (modeMap[el] == maxCount) {
maxEl += "&" + el;
maxCount = modeMap[el];
}
}
return maxEl;
}
이제 기호로 구분 된 모드 요소가있는 문자열을 반환합니다 &
. 결과가 수신되면 해당 &
요소에서 분할 할 수 있으며 모드를 사용할 수 있습니다 .
또 다른 옵션은 다음과 같이 모드 요소의 배열을 반환하는 것입니다.
function modeArray(array) {
if (array.length == 0) return null;
var modeMap = {},
maxCount = 1,
modes = [];
for (var i = 0; i < array.length; i++) {
var el = array[i];
if (modeMap[el] == null) modeMap[el] = 1;
else modeMap[el]++;
if (modeMap[el] > maxCount) {
modes = [el];
maxCount = modeMap[el];
} else if (modeMap[el] == maxCount) {
modes.push(el);
maxCount = modeMap[el];
}
}
return modes;
}
위의 예에서 함수의 결과를 모드 배열로 처리 할 수 있습니다.
modes
에 [array[0]]
초기 값으로. 이렇게하면 modes
. 이것은 트릭을해야합니다var modes = []
==
하기 위해 ===
to의 인스턴스 변경 권장
를 기반으로 밀사 의 ES6 + 응답, 당신은 사용할 수 있습니다 Array.prototype.reduce
내가 아주 매끄러운 모습을 생각한다 (배열을 돌연변이 잠재적으로 분류 터지는와 반대) 귀하의 비교를 할 수 있습니다.
const mode = (myArray) =>
myArray.reduce(
(a,b,i,arr)=>
(arr.filter(v=>v===a).length>=arr.filter(v=>v===b).length?a:b),
null)
기본적으로 null로 설정되어 있습니다. null이 필터링 할 수있는 옵션 인 경우 항상 진실한 응답을 제공하지는 않습니다. 선택적인 두 번째 인수 일 수 있습니다.
다른 다양한 솔루션과 마찬가지로 단점은 '그리기 상태'를 처리하지 않는다는 것입니다. 그러나 이것은 여전히 약간 더 관련된 감소 기능으로 달성 할 수 있습니다.
a=['pear', 'apple', 'orange', 'apple'];
b={};
max='', maxi=0;
for(let k of a) {
if(b[k]) b[k]++; else b[k]=1;
if(maxi < b[k]) { max=k; maxi=b[k] }
}
이 기능을 면접관을위한 퀴즈로 사용하면서 솔루션을 게시합니다.
const highest = arr => (arr || []).reduce( ( acc, el ) => {
acc.k[el] = acc.k[el] ? acc.k[el] + 1 : 1
acc.max = acc.max ? acc.max < acc.k[el] ? el : acc.max : el
return acc
}, { k:{} }).max
const test = [0,1,2,3,4,2,3,1,0,3,2,2,2,3,3,2]
console.log(highest(test))
여기에서 선언적 접근 방식을 시도합니다. 이 솔루션은 각 단어의 발생을 집계하는 개체를 만듭니다. 그런 다음 각 단어의 총 발생 횟수를 개체에서 찾은 가장 높은 값과 비교하여 개체를 배열로 필터링합니다.
const arr = ['hello', 'world', 'hello', 'again'];
const tally = (acc, x) => {
if (! acc[x]) {
acc[x] = 1;
return acc;
}
acc[x] += 1;
return acc;
};
const totals = arr.reduce(tally, {});
const keys = Object.keys(totals);
const values = keys.map(x => totals[x]);
const results = keys.filter(x => totals[x] === Math.max(...values));
다른 솔루션을위한 시간 :
function getMaxOccurrence(arr) {
var o = {}, maxCount = 0, maxValue, m;
for (var i=0, iLen=arr.length; i<iLen; i++) {
m = arr[i];
if (!o.hasOwnProperty(m)) {
o[m] = 0;
}
++o[m];
if (o[m] > maxCount) {
maxCount = o[m];
maxValue = m;
}
}
return maxValue;
}
간결성이 중요하다면 (그렇지 않다면) :
function getMaxOccurrence(a) {
var o = {}, mC = 0, mV, m;
for (var i=0, iL=a.length; i<iL; i++) {
m = a[i];
o.hasOwnProperty(m)? ++o[m] : o[m] = 1;
if (o[m] > mC) mC = o[m], mV = m;
}
return mV;
}
존재하지 않는 멤버를 피해야하는 경우 (예 : 희소 배열), 추가 hasOwnProperty 테스트가 필요합니다.
function getMaxOccurrence(a) {
var o = {}, mC = 0, mV, m;
for (var i=0, iL=a.length; i<iL; i++) {
if (a.hasOwnProperty(i)) {
m = a[i];
o.hasOwnProperty(m)? ++o[m] : o[m] = 1;
if (o[m] > mC) mC = o[m], mV = m;
}
}
return mV;
}
getMaxOccurrence([,,,,,1,1]); // 1
여기에 다른 답변은 undefined 를 반환 합니다.
https://www.w3resource.com/javascript-exercises/javascript-array-exercise-8.php의 또 다른 JS 솔루션
이것도 시도 할 수 있습니다.
let arr =['pear', 'apple', 'orange', 'apple'];
function findMostFrequent(arr) {
let mf = 1;
let m = 0;
let item;
for (let i = 0; i < arr.length; i++) {
for (let j = i; j < arr.length; j++) {
if (arr[i] == arr[j]) {
m++;
if (m > mf) {
mf = m;
item = arr[i];
}
}
}
m = 0;
}
return item;
}
findMostFrequent(arr); // apple
O (n) 복잡성으로 수행하는 또 다른 ES6 방법입니다.
const result = Object.entries(
['pear', 'apple', 'orange', 'apple'].reduce((previous, current) => {
if (previous[current] === undefined) previous[current] = 1;
else previous[current]++;
return previous;
}, {})).reduce((previous, current) => (current[1] >= previous[1] ? current : previous))[0];
console.log("Max value : " + result);
function mode(arr){
return arr.reduce(function(counts,key){
var curCount = (counts[key+''] || 0) + 1;
counts[key+''] = curCount;
if (curCount > counts.max) { counts.max = curCount; counts.mode = key; }
return counts;
}, {max:0, mode: null}).mode
}
이 문제에 대한 나의 해결책이 있지만 숫자와 새로운 '설정'기능을 사용합니다. 그다지 성능이 좋지는 않지만 확실히 이것을 쓰는 데 많은 재미가 있었고 여러 최대 값을 지원합니다.
const mode = (arr) => [...new Set(arr)]
.map((value) => [value, arr.filter((v) => v === value).length])
.sort((a,b) => a[1]-b[1])
.reverse()
.filter((value, i, a) => a.indexOf(value) === i)
.filter((v, i, a) => v[1] === a[0][1])
.map((v) => v[0])
mode([1,2,3,3]) // [3]
mode([1,1,1,1,2,2,2,2,3,3,3]) // [1,2]
그건 그렇고, 이것을 프로덕션에 사용하지 마십시오. 이것은 단지 ES6 및 배열 함수로만 해결할 수있는 방법의 예시 일뿐입니다.
내 해결책은 다음과 같습니다.
function frequent(number){
var count = 0;
var sortedNumber = number.sort();
var start = number[0], item;
for(var i = 0 ; i < sortedNumber.length; i++){
if(start === sortedNumber[i] || sortedNumber[i] === sortedNumber[i+1]){
item = sortedNumber[i]
}
}
return item
}
console.log( frequent(['pear', 'apple', 'orange', 'apple']))
읽기 쉽고 유지 관리가 가능한 코드를 위해 다음과 같이 공유합니다.
function getMaxOcurrences(arr = []) {
let item = arr[0];
let ocurrencesMap = {};
for (let i in arr) {
const current = arr[i];
if (ocurrencesMap[current]) ocurrencesMap[current]++;
else ocurrencesMap[current] = 1;
if (ocurrencesMap[item] < ocurrencesMap[current]) item = current;
}
return {
item: item,
ocurrences: ocurrencesMap[item]
};
}
누군가에게 도움이되기를 바랍니다;)!
이 솔루션은 동점 인 경우 배열의 여러 요소를 반환 할 수 있습니다. 예를 들어, 배열
arr = [ 3, 4, 3, 6, 4, ];
두 가지 모드 값 : 3
및 6
.
여기에 해결책이 있습니다.
function find_mode(arr) {
var max = 0;
var maxarr = [];
var counter = [];
var maxarr = [];
arr.forEach(function(){
counter.push(0);
});
for(var i = 0;i<arr.length;i++){
for(var j=0;j<arr.length;j++){
if(arr[i]==arr[j])counter[i]++;
}
}
max=this.arrayMax(counter);
for(var i = 0;i<arr.length;i++){
if(counter[i]==max)maxarr.push(arr[i]);
}
var unique = maxarr.filter( this.onlyUnique );
return unique;
};
function arrayMax(arr) {
var len = arr.length, max = -Infinity;
while (len--) {
if (arr[len] > max) {
max = arr[len];
}
}
return max;
};
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
var mode = 0;
var c = 0;
var num = new Array();
var value = 0;
var greatest = 0;
var ct = 0;
참고 : ct는 배열의 길이입니다.
function getMode()
{
for (var i = 0; i < ct; i++)
{
value = num[i];
if (i != ct)
{
while (value == num[i + 1])
{
c = c + 1;
i = i + 1;
}
}
if (c > greatest)
{
greatest = c;
mode = value;
}
c = 0;
}
}
const mode = (str) => {
return str
.split(' ')
.reduce((data, key) => {
let counter = data.map[key] + 1 || 1
data.map[key] = counter
if (counter > data.counter) {
data.counter = counter
data.mode = key
}
return data
}, {
counter: 0,
mode: null,
map: {}
})
.mode
}
console.log(mode('the t-rex is the greatest of them all'))
시도해보십시오. 이것은 계정 브라우저 버전을 고려하지 않습니다.
function mode(arr){
var a = [],b = 0,occurrence;
for(var i = 0; i < arr.length;i++){
if(a[arr[i]] != undefined){
a[arr[i]]++;
}else{
a[arr[i]] = 1;
}
}
for(var key in a){
if(a[key] > b){
b = a[key];
occurrence = key;
}
}
return occurrence;
}
alert(mode(['segunda','terça','terca','segunda','terça','segunda']));
이 함수는 2 개 이상의 항목이 동일한 횟수로 나타날 때 배열에서 최신 항목을 반환합니다.
다음은 내장 된 맵을 사용하는 최신 버전입니다 (고유 한 문자열로 변환 할 수있는 것 이상에서 작동 함).
'use strict';
const histogram = iterable => {
const result = new Map();
for (const x of iterable) {
result.set(x, (result.get(x) || 0) + 1);
}
return result;
};
const mostCommon = iterable => {
let maxCount = 0;
let maxKey;
for (const [key, count] of histogram(iterable)) {
if (count > maxCount) {
maxCount = count;
maxKey = key;
}
}
return maxKey;
};
console.log(mostCommon(['pear', 'apple', 'orange', 'apple']));
var array = [1, 3, 6, 6, 6, 6, 7, 7, 12, 12, 17],
c = {}, // counters
s = []; // sortable array
for (var i=0; i<array.length; i++) {
c[array[i]] = c[array[i]] || 0; // initialize
c[array[i]]++;
} // count occurrences
for (var key in c) {
s.push([key, c[key]])
} // build sortable array from counters
s.sort(function(a, b) {return b[1]-a[1];});
var firstMode = s[0][0];
console.log(firstMode);
이것을 시도 할 수 있습니다.
// using splice()
// get the element with the highest occurence in an array
function mc(a) {
var us = [], l;
// find all the unique elements in the array
a.forEach(function (v) {
if (us.indexOf(v) === -1) {
us.push(v);
}
});
l = us.length;
while (true) {
for (var i = 0; i < l; i ++) {
if (a.indexOf(us[i]) === -1) {
continue;
} else if (a.indexOf(us[i]) != -1 && a.length > 1) {
// just delete it once at a time
a.splice(a.indexOf(us[i]), 1);
} else {
// default to last one
return a[0];
}
}
}
}
// using string.match method
function su(a) {
var s = a.join(),
uelms = [],
r = {},
l,
i,
m;
a.forEach(function (v) {
if (uelms.indexOf(v) === -1) {
uelms.push(v);
}
});
l = uelms.length;
// use match to calculate occurance times
for (i = 0; i < l; i ++) {
r[uelms[i]] = s.match(new RegExp(uelms[i], 'g')).length;
}
m = uelms[0];
for (var p in r) {
if (r[p] > r[m]) {
m = p;
} else {
continue;
}
}
return m;
}
O (n) 복잡성으로 해결할 수 있습니다.
var arr = [1,3,54,56,6,6,1,6];
var obj = {};
/* first convert the array in to object with unique elements and number of times each element is repeated */
for(var i = 0; i < arr.length; i++)
{
var x = arr[i];
if(!obj[x])
obj[x] = 1;
else
obj[x]++;
}
console.log(obj);//just for reference
/* now traverse the object to get the element */
var index = 0;
var max = 0;
for(var obIndex in obj)
{
if(obj[obIndex] > max)
{
max = obj[obIndex];
index = obIndex;
}
}
console.log(index+" got maximum time repeated, with "+ max +" times" );
위 코드를 실행하려면 크롬 콘솔에 복사하여 붙여 넣기 만하면됩니다.
이 함수는 모든 유형의 정보에 대한 일반 함수입니다. 요소의 발생을 계산 한 다음 최대 발생 요소가있는 배열을 반환합니다.
function mode () {
var arr = [].slice.call(arguments);
if ((args.length == 1) && (typeof args[0] === "object")) {
args = args[0].mode();
}
var obj = {};
for(var i = 0; i < arr.length; i++) {
if(obj[arr[i]] === undefined) obj[arr[i]] = 1;
else obj[arr[i]]++;
}
var max = 0;
for (w in obj) {
if (obj[w] > max) max = obj[w];
}
ret_val = [];
for (w in obj) {
if (obj[w] == max) ret_val.push(w);
}
return ret_val;
}
function mode(){
var input = $("input").val().split(",");
var mode = [];
var m = [];
var p = [];
for(var x = 0;x< input.length;x++){
if(m.indexOf(input[x])==-1){
m[m.length]=input[x];
}}
for(var x = 0; x< m.length;x++){
p[x]=0;
for(var y = 0; y<input.length;y++){
if(input[y]==m[x]){
p[x]++;
}}}
for(var x = 0;x< p.length;x++){
if(p[x] ==(Math.max.apply(null, p))){
mode.push(m[x]);
}}
$("#output").text(mode);}
여기 내 방식입니다. 데이터를 그룹화하려고합니다.
const _ = require("underscore")
var test = [ 1, 1, 2, 1 ];
var groupResult = _.groupBy(test, (e)=> e);
groupResult는 다음과 같아야합니다.
{
1: [1, 1, 1]
2: [2]
}
그런 다음 가장 긴 배열을 가진 속성을 찾으십시오.
function findMax(groupResult){
var maxArr = []
var max;
for(var item in groupResult){
if(!max) {
max = { value:item, count: groupResult[item].length } ;
maxArr.push(max);
continue;
}
if(max.count < groupResult[item].length){
maxArr = [];
max = { value:item, count: groupResult[item].length }
maxArr.push(max)
} else if(max === groupResult[item].length)
maxArr.push({ value:item, count: groupResult[item].length })
}
return maxArr;
}
완전한 코드는 다음과 같습니다.
const _ = require("underscore")
var test = [ 1, 1, 2, 1 ];
var groupResult= _.groupBy(test, (e)=> e);
console.log(findMax(groupResult)[0].value);
function findMax(groupResult){
var maxArr = []
var max;
for(var item in groupResult){
if(!max) {
max = { value:item, count: groupResult[item].length } ;
maxArr.push(max);
continue;
}
if(max.count < groupResult[item].length){
maxArr = [];
max = { value:item, count: groupResult[item].length }
maxArr.push(max)
} else if(max === groupResult[item].length)
maxArr.push({ value:item, count: groupResult[item].length })
}
return maxArr;
}
var cats = ['Tom','Fluffy','Tom','Bella','Chloe','Tom','Chloe'];
var counts = {};
var compare = 0;
var mostFrequent;
(function(array){
for(var i = 0, len = array.length; i < len; i++){
var word = array[i];
if(counts[word] === undefined){
counts[word] = 1;
}else{
counts[word] = counts[word] + 1;
}
if(counts[word] > compare){
compare = counts[word];
mostFrequent = cats[i];
}
}
return mostFrequent;
})(cats);
ES6를 사용하면 다음과 같이 메소드를 연결할 수 있습니다.
function findMostFrequent(arr) {
return arr
.reduce((acc, cur, ind, arr) => {
if (arr.indexOf(cur) === ind) {
return [...acc, [cur, 1]];
} else {
acc[acc.indexOf(acc.find(e => e[0] === cur))] = [
cur,
acc[acc.indexOf(acc.find(e => e[0] === cur))][1] + 1
];
return acc;
}
}, [])
.sort((a, b) => b[1] - a[1])
.filter((cur, ind, arr) => cur[1] === arr[0][1])
.map(cur => cur[0]);
}
console.log(findMostFrequent(['pear', 'apple', 'orange', 'apple']));
console.log(findMostFrequent(['pear', 'apple', 'orange', 'apple', 'pear']));
두 요소에 동일한 발생이 있으면 두 요소를 모두 반환합니다. 그리고 그것은 모든 유형의 요소와 함께 작동합니다.
arr
해당 변수가 이미 매개 변수로 정의 된 범위 내 에서 변수를 사용해서는 안됩니다 . 이로 인해 사용되는 브라우저에 따라 버그가 발생할 수 있습니다.
arr
로 불린다 arr.indexOf(cur)
? 맨 위 매개 변수 또는 내부의 매개 변수가 감소합니까 ??