#javascript #arrays #string #filter #split
#javascript #массивы #строка #Фильтр #разделить
Вопрос:
У меня есть массив строк :
let arr = ["cap:1", "col:red", "cap:3", "cap:1", "col:blue", "screen:yes"]
и я хочу иметь новый массив с одним элементом из каждой категории подстрок («cap», «col», «screen»), с наименьшим индексом:
let newArray = ["cap:1","col:red","screen:yes"]
//"cap:1" from newArray is arr[0]
Я пробовал этот способ:
const newArr = (arr) => {
let c= []
let c = [...c, arr[0]]
for(let i = 1; i<arr.length; i ){
for (let j=0; j<c.length; j ){
if(arr[i].split(":")[0] !== c[j].split(":")){
c = [...c, arr[i]]
}
}
}
return c
}
но это переходит в бесконечный цикл, и результат выглядит примерно так: ["cap:1","col:red","col:red","col:red","col:red","col:red","col:red","col:red"...
Не могли бы вы мне помочь?
Спасибо!
Ответ №1:
Это продолжается бесконечный цикл, поскольку существует два вложенных цикла for, и один из вложенных циклов for повторяет постоянно увеличивающийся массив. Вместо этого у вас может быть объект, который будет действовать как ссылка.
let arr = ["cap:1", "col:red", "cap:3", "cap:1", "col:blue", "screen:yes"];
const newArr = (arr) => {
let c = [];
const suffixObj = {};
for (let i = 0; i < arr.length; i ) {
const getPrefix = arr[i].split(":")[0];
if (!suffixObj.hasOwnProperty(getPrefix)) {
c.push(arr[i]);
suffixObj[getPrefix] = true
}
}
return c
};
console.log(newArr(arr))
Ответ №2:
Вы могли бы взять a Set
с массивом разделенных первых частей.
В результате получаем массив из набора.
const
array = ["cap:1", "col:red", "cap:3", "cap:1", "col:blue", "screen:yes"],
types = [...new Set(array.map(s => s.split(':', 1)[0]))];
console.log(types);
Ответ №3:
Ваша логика не имеет способа определить, что префикс текущего элемента не был найден newArr
. Кроме того, в условии arr[i].split(":")[0] !== c[j].split(":")
вы сравниваете строку с массивом, который всегда возвращает true
— string !== array .
Возможно, вы намеревались написать arr[i].split(":")[0] !== c[j].split(":")[0]
, что все равно не дало бы вам желаемого результата.
Вы можете отказаться от внутреннего цикла и проверить каждый элемент на newArr
использование c.every(el => !...)
следующим образом:
let arr = ["cap:1", "col:red", "cap:3", "cap:1", "col:blue", "screen:yes"];
const newArr = (arr) => {
let c = [arr[0]];
for(let i = 1; i<arr.length; i ) {
if( c.every(el => !arr[i].startsWith( el.split(':')[0] )) ) {
c = [ ...c, arr[i] ];
}
}
return c;
}
console.log( newArr( arr ) );
Ответ №4:
Это отличный вариант использования Array.Reduce . Вы можете уменьшить множество значений вашего массива в компактный объект, разделив записи на ключевые значения и просто взяв первую запись для данного ключа. Что-то подобное должно сработать для вас:
const firstOfGroup = arr => arr.reduce((result, currentValue) => {
const parts = currentValue.split(':');
const key = parts[0];
const value = parts[1];
if (!result.hasOwnProperty(key)) {
result[key] = value;
}
return resu<
});
Если вам конкретно нужны результаты, помещенные в массив, вы можете повторно собрать части в этот формат, но итерация по результирующему объекту должна быть достаточно эффективной.
Ответ №5:
Вот решение, которое может вам помочь! Сначала вам нужно сопоставить все данные, чтобы получить поток ключ-значение. Затем этот поток можно уменьшить, чтобы сохранить только первое вхождение.
let newArr = data.map(function(item){
return item.split(":")
}).reduce(function(acc, curr){
if(acc[curr[0]] === undefined){
acc[curr[0]] = curr[1]
}
return acc
})