在一个数组中对所有非唯一值进行嵌套排序

5

我对JavaScript还比较陌生,我试图构建一些我在挑战中发现的函数。我已经解决了这个问题,但我感觉这是一种非常复杂的方式,有没有更快的方法?

基本上answer(array)应该将其转换为:

const array = [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20];

变成这样:

newArray = [[1,1,1,1],[2,2,2], 4,5,10,[20,20], 391, 392,591];

以下是我的代码:

const array = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];

const duplicates = arr =>
    arr.reduce((a, b) => ({ ...a,
        [b]: (a[b] || 0) + 1
    }), {})

array.sort((a, b) => a - b);
let array1 = duplicates(array);
var values = Object.values(array1);
var keys = Object.keys(array1);
var newArray = [];

for (let i = 0; i < keys.length; i++) {
    let tempArray = [];
    for (let j = 0; j < values[i]; j++) {
        tempArray.push(keys[i]);
    }
    newArray.push(tempArray);
}
console.log(newArray);

这个重复函数来自这篇有关查找重复值的帖子

5个回答

4

看一下这个一行代码。猜测这就是你所需的。

请注意,这并不是最有效的方法 - 但我想这很漂亮!

const array = [1,2,4,591,392,391,2,5,10,2,1,1,1,20,20];
const newArray = [...new Set(array)].sort((a, b) => a-b).map(e => new Array(array.filter( i => i === e).length).fill(e)).map(e => e.length === 1 ? e[0] : e);
console.log(newArray);


原理:

  1. 我们从数组中创建一个具有唯一值的集合 [...new Set(array)]
  2. 我们将集合的键进行排序 .sort((a, b) => a-b)
  3. 我们循环每个值,并计算该值在数组中出现的次数 .map(e => new Array(array.filter( i => i === e).length);
  4. 在最后一步,我们用上面的集合中的值和数量填充新数组 .fill(e)
  5. 我们遍历数组,并将只包含单个值的条目展平 .map(e => e.length === 1 ? e[0] : e)

谢谢,这正是我想要的,它可能不是最快的,但我的目标是学习JavaScript中的数组方法。 - Marelons

2

您的方法已经足够好了(快速)。我对代码进行了一些修改,使用parseInt()将键转换回数字而不是字符串。同时确保单个元素不会嵌套(与您在原始帖子中期望的输出相同)。

const array = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];

const duplicates = arr =>
    arr.reduce((a, b) => ({ ...a,
        [b]: (a[b] || 0) + 1
    }), {})

array.sort((a, b) => a - b);
let array1 = duplicates(array);
var values = Object.values(array1);
var keys = Object.keys(array1);
var newArray = [];

for (let i = 0; i < keys.length; i++) {
    let tempArray = [];
    if (values[i] === 1) {
        newArray.push(parseInt(keys[i]));
    } else {
        newArray.push(Array(values[i]).fill(parseInt(keys[i])));
    }
}

console.log(newArray);


2

给定一个升序排列的数组,你可以定义两个变量,一个存储元素排序后的唯一数组,另一个存储元素在数组中出现的次数。

之后,你可以遍历唯一数组,如果某个元素的出现次数大于1,则返回一个由该元素填充且长度为该元素出现次数的数组;否则只返回该元素本身。

const sortedArray = [1, 1, 1, 1, 2, 2, 2, 4, 5, 10, 20, 20, 391, 392, 591]

const sortedUnique = Array.from(new Set(sortedArray))
const occurences = sortedArray.reduce((acc, el) => {
  acc.set(el, (acc.get(el) || 0) + 1)
  return acc
}, new Map())

const res = sortedUnique.map((el) =>
  occurences.get(el) > 1 ? Array(occurences.get(el)).fill(el) : el
)

console.log(res)


2
你已经快完成了,但还有一些需要改进的地方。

  const array = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
array.sort((a, b) => a - b);
let groupedArr = array.reduce((acc, a) => {
  acc[a] = acc[a] || [];
  acc[a].push(a);
  return acc;
}, {});

let newArray = [];

for (a in groupedArr) {
  if (groupedArr[a].length > 1) {
    newArray.push(groupedArr[a]);
  } else {
    newArray.push(groupedArr[a][0]);
  }
}
console.log(newArray);


谢谢,看起来好多了。你能简要解释一下 groupedArr 函数是如何工作的吗? - Marelons
1
@Marelons 在 reduce 函数中,我们正在对数字进行分组,其中数字本身是键。 例如:{ 1:[1, 1, 1, 1], 2:[2, 2]} - Sheelpriy

1
解决方案 #1

const array = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];

// [...array] prevents mutation of original array when invoking sort method
const sortedNested = [...array].sort().reduce((acc, cur, idx, org) => {
  if (!acc[cur]) {
    acc[cur] = cur;
  } else if (Array.isArray(acc[cur])) {
    acc[cur].push(cur);
  } else {
    acc[cur] = [cur, cur];
  }

  return idx === org.length - 1 ? Object.values(acc) : acc;
}, {});

console.log(sortedNested);

解决方案 #2

const array = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];

// get distinct array elements
const distinct = Array.from(new Set(array));

// map to desired output
const nested = distinct.map(value => {
  const length = array.filter(_value => _value === value).length;

  return length === 1 ? value : Array.from({length}).fill(value);
  
})
// sort ascending
.sort(
    // return a - b; if either a or b is array get their first element
    (a, b) => (Array.isArray(a) ? a[0] : a) - (Array.isArray(b) ? b[0] : b)
);

console.log(nested);


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接