Как будто вы пытаетесь получить доступ к объекту, который является null
. Рассмотрим ниже пример:
TypeA objA;
. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException
, что имеет смысл.
См. Также этот пример:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Вы можете извлечь уникальные значения, используя Set
, затем отсортировать их (поскольку сортировка массива массивов более сложна), затем использовать array.reduce
, чтобы получить все элементы в исходном массиве, и нажать либо одно значение, если уникальное в противном случае массив значений (не знаю, зачем вам это нужно, но все же ..)
Дополнительная справочная документация:
Рабочий код ниже:
let arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
// I want to create this [[1,1,1,1],[2,2,2], 4,5,10,[20,20], 391, 392,591]
console.log([...new Set(arr)].sort((a,b) => a - b).reduce((accumulator, next) => {
const filtered = arr.filter(i => i === next);
return accumulator.push(filtered.length === 1 ? filtered[0] : filtered), accumulator
}, []));
Хотя существуют и другие подходы, всякий раз, когда мне нужно разобрать уникальные значения из массива таким образом, я создам объект со свойствами объекта, представляющими группировки значений массива
{ 1: [1, 1, 1], 2: [2 , 2, 2], 4: [4], 5: [5] ...}
Затем вы можете используйте нативный метод объекта, чтобы получить все ключи или значения от объекта, если вам нужно (или если ваша конечная цель отличается, вы можете использовать объект так, как это необходимо)
Object.keys(obj)
// or
Object.values(obj)
Для вашего случая, это будет выглядеть как
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const obj = arr.reduce((accum, val) => {
accum[val] = accum[val] || [];
accum[val].push(val);
return accum;
}, {});
const finalArr = Object.values(obj).map(val => val.length > 1 ? val : val[0]);
console.log(finalArr);
Вы можете:
1) перебрать массив, построить карту частот из чисел
2) взять и отсортировать ключ карты частот в порядке возрастания
[116 ] 3) построить новый массив из информации в карте частот
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const obj = arr.reduce((acc, c) => {
return acc[c] = (acc[c] || 0) + 1, acc;
}, {});
// {"1":4,"2":3,"4":1,"5":1,"10":1,"20":2,"391":1,"392":1,"591":1}
const keys = Object.keys(obj).sort((a, b) => a - b).map(Number);
// [1,2,4,5,10,20,391,392,591]
const out = keys.map((key) => {
return obj[key] > 1 ? Array(obj[key]).fill(key) : key;
});
// [[1,1,1,1],[2,2,2],4,5,10,[20,20],391,392,591]
console.log(JSON.stringify(out));
Вы можете сделать это разными способами. Но если вы хотите добиться наилучших результатов, вы должны избегать n квадратных петель .
Так можно создать словарь подсчета значений. И перебрать ключи объекта в отсортированном порядке.
Использование Array.reduce
для создания объекта подсчета элементов массива. и Array.fill
заполнить массив одинаковыми значениями.
//Given Array
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
//Dictionary with count of each values in array
const arrCountObj = arr.reduce((acc, el) => {
if (acc[el]) {
acc[el] += 1
} else {
acc[el] = 1
}
return acc
}, {})
console.log(arrCountObj)
//Looping over sorted dictionary keys to create array based on condition
var out = Object.keys(arrCountObj).sort((a, b) => a - b).map(x => arrCountObj[x] > 1 ? new Array(arrCountObj[x]).fill(+x) : arrCountObj[x])
console.log(out)
Сложность времени: O (nlogn)
blockquote>
Вы можете сосчитать вхождения и затем использовать этот объект для создания вашего окончательного массива.
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const count = arr.reduce((acc, val) => {
acc[val] = acc[val] + 1 || 1;
return acc;
}, {});
const result = Object
.keys(count)
.sort((a, b) => a - b)
.map((key) => count[key] === 1 ? +key : Array.from({ length: count[key] }).fill(+key));
console.log(result);
Вы можете использовать reduce
, а затем Array.fill
. Здесь редукция создаст объект, подобный этому
{
"1": 4,
"2": 3,
"4": 1,
"5": 1,
"10": 1,
"20": 2,
"391": 1,
"392": 1,
"591": 1
}
, что означает, что есть 4
1s
, 3
2s
и так далее. Затем вы можете использовать заполнение массива после итерации этого объекта. Синтаксис массива fill
имеет вид arr.fill(value[, start[, end]])
. Таким образом, в нашем случае new Array(k[keys]).fill(+keys, 0, k[keys])
будет создан новый массив длины 4
, 3
и т. Д., За исключением 1
и 0 Индекс заполняется ключом
let arr = [1, 2, 4, 591, 392, 391,1, 2, 5, 10, 2, 1, 1, 1, 20, 20];
let k = arr.reduce(function(acc, curr) {
if (curr in acc) {
acc[curr] += 1;
} else {
acc[curr] = 1
}
return acc;
}, {});
let grouped = [];
for (let keys in k) {
if (k[keys] !== 1) {
grouped.push(new Array(k[keys]).fill(+keys, 0))
} else {
grouped.push(+keys)
}
}
console.log(grouped)