我想按元素頻率對陣列進行排序。我的代碼適用于字串陣列,但不適用于數字陣列:
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a 1 : a), 0);
function frequencySort(arr){
let d = {}
arr.forEach(i => d[i] = countOccurrences(arr,i))
arr.sort(function(a,b){
return d[b] - d[a]
})
return arr
}
frequencySort(['a','b','b','b','c','c'])) returns [ 'b', 'b', 'b', 'c', 'c', 'a' ]
frequencySort([4, 6, 2, 2, 6, 4, 4, 4]) returns [ 4, 4, 4, 4, 6, 2, 2, 6 ]
有人可以幫我嗎?謝謝!
uj5u.com熱心網友回復:
您的字母有效的唯一原因是因為您沒有任何兩個字母的相同數字,而在您的數字中,您有 2 和 6 中的 2 個。
這是您的代碼段,但有 2 個 a 和 2 個 c。你會看到它和數字一樣亂序。
顯示代碼片段
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a 1 : a), 0);
function frequencySort(arr){
let d = {}
arr.forEach(i => d[i] = countOccurrences(arr,i))
arr.sort(function(a,b){
return d[b] - d[a]
})
return arr
}
console.log(frequencySort(['a','b','b','b','c','c', 'a']))
您需要一種對出現次數相同的實體進行排序的方法。我調整了您的 forEach 回圈以將每個字母的最后一個索引提供給您的b物件,然后更改您的排序以使用該索引,以防出現次數相同。
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a 1 : a), 0);
function frequencySort(arr){
let d = {}
arr.forEach((i,index) => d[i] = {
num: countOccurrences(arr,i),
i: index
});
arr.sort(function(a,b){
let diff = d[b].num - d[a].num;
if(diff == 0)
diff = d[b].i - d[a].i;
return diff;
})
return arr
}
console.log(frequencySort(['a','b','b','b','c','c', 'a']))
console.log(frequencySort([4, 6, 2, 2, 6, 4, 4, 4]));
uj5u.com熱心網友回復:
它與元素是字母或數字無關。在你的字母陣列中,每個字母都有唯一的出現次數(3、2、1),因此它們按你想要的方式排序。
但是,在您的數字陣列中,“2”和“6”都各出現 2 次。因此,您的排序回呼函式為它們回傳 0,并且它們被sort函式視為等序。
uj5u.com熱心網友回復:
在您的數字陣列中,您的數字 2 與 6 的數量相同,并且您的排序函式不關心實際值,它只關心它們的計數。所以在你的例子 2 和 6 中都有相同的優先級。
如果元素的出現次數相同,您希望調整排序函式以比較元素的值。您需要對要接受的所有資料型別實施單獨的比較,并決定是否需要升序/降序。
以下是數字和字串元素的基本示例:
const countOccurrences = (arr, val) => arr.reduce((a, v) => (v === val ? a 1 : a), 0);
function frequencySort(arr){
let d = {}
arr.forEach(i => d[i] = countOccurrences(arr,i))
arr.sort(function(a,b){
const r = d[b] - d[a]
if (r != 0) return r
switch (typeof d[a]) {
case 'number': return a - b
case 'string': return a.localeCompare(b)
default: return 0
}
})
return arr
}
console.log(frequencySort(['a','b','b','b','c','c'])) // returns [ 'b', 'b', 'b', 'c', 'c', 'a' ]
console.log(frequencySort([4, 6, 2, 2, 6, 4, 4, 4])) // returns [ 4, 4, 4, 4, 2, 2, 6, 6 ]
uj5u.com熱心網友回復:
一種可能的方法是首先通過reduce任務收集特定于專案的組陣列中的所有相等的陣列專案......
console.log(
"grouped ['a','b','b','b','c','c'] ...",
['a','b','b','b','c','c'].reduce((index, item) => {
const groupList =
index[`${ (typeof item) }_${ item }`] ??= [];
groupList.push(item);
return index;
}, {})
);
console.log(
"grouped [4, 6, 2, 2, 6, 4, 4, 4,'4','2','2'] ...",
[4, 6, 2, 2, 6, 4, 4, 4,'4','2','2'].reduce((index, item) => {
const groupList =
index[`${ (typeof item) }_${ item }`] ??= [];
groupList.push(item);
return index;
}, {})
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
最終的計算然后必須通過Object.values... 將臨時結果(如上所示)轉換為相等項陣列的陣列,其中前者sort按每個陣列的長度(表示項頻率)進行第一次編輯,第二次,對于等長的陣列',通過每個陣列的第一項的語言環境比較。最終結果是排序陣列的flatted 版本......
function sortItemsByFrequency(arr) {
const groupedItems = arr.reduce((index, item) => {
const groupList =
index[`${ (typeof item) }_${ item }`] ??= [];
groupList.push(item);
return index;
}, {});
return Object
.values(groupedItems)
.sort((a, b) =>
// - sort by frequency first indicated by an
// array's length.
// - the higher frequency count wins.
b.length - a.length ||
// in case of equal frequency counts do a
// locale compare of both array's first items.
b[0].toLocaleString().localeCompare(a[0].toLocaleString())
)
.flat();
}
console.log(
"sortItemsByFrequency(['a','b','b','b','c','c']) ...",
sortItemsByFrequency(['a','b','b','b','c','c'])
);
console.log(
"sortItemsByFrequency([4, 6, 2, 2, 6, 4, 4, 4,'4','2','2']) ...",
sortItemsByFrequency([4, 6, 2, 2, 6, 4, 4, 4,'4','2','2'])
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/314577.html
標籤:javascript 排序
