Bir JavaScript dizisinde hangi öğenin en yüksek oluşum ( mod ) olduğunu belirlemenin zarif bir yolunu arıyorum .
Örneğin,
['pear', 'apple', 'orange', 'apple']
'apple'
eleman en sık biridir.
Bir JavaScript dizisinde hangi öğenin en yüksek oluşum ( mod ) olduğunu belirlemenin zarif bir yolunu arıyorum .
Örneğin,
['pear', 'apple', 'orange', 'apple']
'apple'
eleman en sık biridir.
Yanıtlar:
Bu sadece moddur. İşte hızlı, optimize edilmemiş bir çözüm. O (n) olmalıdır.
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'dan beri javascript'te bazı gelişmeler oldu - bir seçenek daha ekleyeceğimi düşündüm. Aslında bir sorun olana kadar verimlilikle daha az ilgileniyorum, bu yüzden "zarif" kod tanımım (OP tarafından öngörüldüğü gibi) okunabilirliği destekliyor - ki bu tabii ki özneldir ...
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
Bu özel örnekte, kümenin iki veya daha fazla öğesi eşit oluşumlara sahipse, dizide en son görünen öğe döndürülür. Ayrıca, orijinal dizinizi değiştireceğini de belirtmek gerekir - bu, Array.slice
önceden bir arama ile dilerseniz engellenebilir .
Düzenleme: bazılarıyla örnek güncellenen ES6 şişman oklar yüzünden 2015 oldu ve ben onlar geriye dönük uyumluluk konusunda endişeleriniz varsa size bu bulabilirsiniz ... Oldukça bakmak düşünüyorum düzeltme geçmişinde .
Gereğince George Jempty's
bağları için algoritma hesabına sahip olması isteği, ben değiştirilmiş bir versiyonunu teklif Matthew Flaschen's
algoritması.
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;
}
Bu, şimdi bir &
sembol ile ayrılmış mod öğelerine sahip bir dize döndürecektir . Sonuç alındığında, o &
öğeye bölünebilir ve kip (ler) inize sahip olursunuz.
Diğer bir seçenek de, aşağıdaki gibi bir mod öğesi (ler) dizisi döndürmektir:
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;
}
Yukarıdaki örnekte, işlevin sonucunu bir mod dizisi olarak işleyebileceksiniz.
modes
için [array[0]]
başlangıç değeri olarak. Bu, içinde kopyalarınızın olmasını sağlayacaktır modes
. Bu hile yapmalıvar modes = []
==
sağlamak ===
için örneklerini değiştirmenizi tavsiye ederiz
Emissary'nin ES6 + cevabına dayanarak, Array.prototype.reduce
karşılaştırmanızı yapmak için kullanabilirsiniz (dizinizi sıralamak, patlatmak ve potansiyel olarak değiştirmenin aksine), ki bence oldukça şık görünüyor.
const mode = (myArray) =>
myArray.reduce(
(a,b,i,arr)=>
(arr.filter(v=>v===a).length>=arr.filter(v=>v===b).length?a:b),
null)
Varsayılanı null olarak ayarlıyorum, bu size her zaman doğru bir yanıt vermeyecek, eğer null filtreleme yaptığınız olası bir seçenekse, belki bu isteğe bağlı bir ikinci argüman olabilir
Diğer çeşitli çözümlerde olduğu gibi dezavantajı, 'çekme durumlarını' ele almamasıdır, ancak bu yine de biraz daha ilgili bir azaltma işlevi ile başarılabilir.
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] }
}
Bu işlevi görüşmeciler için bir test olarak kullandığım için çözümümü gönderiyorum:
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))
Burada açıklayıcı bir yaklaşım denemek. Bu çözüm, her bir kelimenin geçtiği yeri belirleyecek bir nesne oluşturur. Daha sonra, her kelimenin toplam oluşumlarını nesnede bulunan en yüksek değerle karşılaştırarak nesneyi bir diziye doğru filtreler.
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));
Başka bir çözüm zamanı:
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;
}
Kısalık önemliyse (önemli değil), o zaman:
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;
}
Varolmayan üyelerden kaçınılacaksa (örneğin seyrek dizi), ek bir hasOwnProperty testi gereklidir:
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
Buradaki diğer cevaplar tanımsız olarak dönecektir .
Başka bir JS çözümü: https://www.w3resource.com/javascript-exercises/javascript-array-exercise-8.php
Bunu da deneyebilir miyim:
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
İşte bunu O (n) karmaşıklığı ile yapmanın başka bir ES6 yolu
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
}
İşte bu soruna çözümüm, ancak sayılarla ve yeni 'Set' özelliğini kullanarak. Çok performanslı değil ama kesinlikle bunu yazarken çok eğlendim ve birden fazla maksimum değeri destekliyor.
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]
Bu arada bunu üretim için kullanmayın, bu sadece bunu sadece ES6 ve Array işlevleriyle nasıl çözebileceğinizin bir örneğidir.
İşte benim çözümüm: -
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']))
Okuması gerçekten kolay, bakımı yapılabilir kod uğruna bunu paylaşıyorum:
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]
};
}
Umarım birine yardımcı olur;)!
Bu çözüm, bağ olması durumunda bir dizinin birden çok öğesini döndürebilir. Örneğin, bir dizi
arr = [ 3, 4, 3, 6, 4, ];
iki mod değerine sahiptir: 3
ve 6
.
İşte çözüm.
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;
Not: ct, dizinin uzunluğudur.
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'))
Siz de deneyin, bu hesap tarayıcı versiyonunu almaz.
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']));
Lütfen unutmayın, bu işlev, 2 veya daha fazla giriş aynı sayıda göründüğünde dizideki en son oluşumu döndürür!
Yerleşik haritaları kullanan modern sürüm burada (bu nedenle benzersiz dizelere dönüştürülebilen şeylerden daha fazlası üzerinde çalışır):
'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']));
Sanırım iki yaklaşımınız var. Her ikisinin de avantajları var.
Sıralayın ve ardından Sayın veya Döngü ile sayın ve sizin yerinize sayımı yapmak için bir karma tablo kullanın.
Hashtable güzeldir çünkü işlemeyi bitirdikten sonra aynı zamanda tüm farklı öğelere sahip olursunuz. Yine de milyonlarca öğeniz varsa, çoğaltma oranı düşükse, karma tablo çok fazla bellek kullanabilir. Sırala ve sonra say yaklaşımı, çok daha kontrol edilebilir bir bellek ayak izine sahip olacaktır.
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);
Bunu deneyebilirsiniz:
// 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) karmaşıklığında çözebilirsin
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" );
Yukarıdaki kodu çalıştırmak için Chrome konsoluna kopyalayıp yapıştırmanız yeterlidir.
Bu işlev, her tür bilgi için genel bir işlevdir. Öğelerin oluşumunu sayar ve ardından en fazla meydana gelen öğelere sahip dizi döndürür.
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);}
İşte benim yolum. Veri yumruğunu gruplamaya çalışıyorum.
const _ = require("underscore")
var test = [ 1, 1, 2, 1 ];
var groupResult = _.groupBy(test, (e)=> e);
GroupResult olmalıdır
{
1: [1, 1, 1]
2: [2]
}
Ardından en uzun diziye sahip özelliği bulun
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;
}
Tam kod gibi görünüyor
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 ile yöntemi şu şekilde zincirleyebilirsiniz:
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']));
İki öğenin aynı oluşumu varsa, her ikisini de döndürür. Ve her tür elemanla çalışır.
arr
Değişkeni, değişkenin zaten bir parametre olarak tanımlandığı bir kapsam içinde kullanmamalısınız . Bu, hangi tarayıcının kullanıldığına bağlı olarak hatalara yol açabilir.
arr
atıfta bulunulur arr.indexOf(cur)
? En üst parametre mi yoksa azaltmanın içindeki mi?