#javascript #arrays
#javascript #массивы
Вопрос:
Я хочу разбить строку на массив с максимальным количеством символов 15 на элемент в массиве. Я хочу выполнить это с array.reduce
помощью . Может кто-нибудь указать мне правильное направление?
Глядя на это:
const str = 'Lorem ipsum dolor sit amet consectetur adipiscing elit'
Я хочу получить такой результат:
const result = ['Lorem ipsum', 'dolor sit amet', 'consectetur', 'adipiscing elit']
Комментарии:
1. ну, попробуйте на самом деле использовать array reduce
2. почему
reduce
? звучит слишком сложно3.
const result = str.split(' ').reduce((a,i)=>(a.length?(()=>{let n=a.length-1,s=a[n],l=s.length;((s i).length<15)?a[n] =' ' i:a.push(i)})():a.push(i),a),[]);
4. Для записи также возможно с регулярным выражением. Однако очень не рекомендуется — я просто сделал это для развлечения:
/(?<=^|s).{1,15}(?=s|$)/g
сопоставьте до 15 символов, но они должны быть целыми словами, поэтому они не будут соответствовать середине слова и не будут содержать пробел перед / после слова.[...str.matchAll(regex)].flat()
выдает ожидаемый результат.
Ответ №1:
Для каждой reduce
итерации объединяйте с последним предложением, а затем сравнивайте длину с максимальной, если она превышает, добавьте новое предложение, иначе замените последнее предложение объединенным
const str = 'Lorem ipsum dolor sit amet consectetur adipiscing elit'
const res = str.split(' ').reduce((acc, word) => {
const lastSentence = acc.pop()
const currentConcatnated = [lastSentence, word].filter(Boolean).join(' ')
if (currentConcatnated.length > 15) {
acc.push(lastSentence)
acc.push(word)
} else {
acc.push(currentConcatnated)
}
return acc
}, [])
console.log(res)
Комментарии:
1. Вот и все, спасибо! По какой-то причине мне было трудно понять, что такое Reduce.
2. @zero мне тоже сложно в первый раз, главное, что я убрал после долгой практики, — не забывать возвращать накопленное значение после каждой итерации
Ответ №2:
Вот более понятный подход, который все еще используется Array.prototype.reduce()
. Это позволяет избежать доступа к последнему элементу, acc
если он пуст, утверждая lastIndex >= 0
, что это не первая итерация.
const str = 'Lorem ipsum dolor sit amet consectetur adipiscing elit';
const result = str.split(' ').reduce((acc, cur) => {
const lastIndex = acc.length - 1;
const val = ' ' cur;
if (lastIndex >= 0 amp;amp; acc[lastIndex].length val.length <= 15) {
acc[lastIndex] = val;
} else {
acc.push(cur);
}
return acc;
}, []);
console.log(result);
Ответ №3:
Это еще одна реализация, использующая альтернативные приемы. Array#reduce
- Оператор объединения
??
с нулевым значением для дополнительной безопасности. Array#concat
, поэтому никогда не изменяет аргумент массива. Это не обязательно, но это полезный трюк для других ситуаций, когда мутации нецелесообразны.
const str = 'Lorem ipsum dolor sit amet consectetur adipiscing elit';
const result = str.split(/s /); //split on any amount of whitespace
.reduce((acc, word) => {
//get the last item but start with an empty string if `acc` is empty
const last = acc[acc.length - 1] ?? "";
//construct the potential new entry and remove extra spaces from start/end
const newLast = `${last} ${word}`.trim();
if (newLast.length > 15) //if too long
return acc.concat(word); // just add the word as a new element
return acc.slice(0, -1) //take everything but the last item
.concat(newLast); //append the new element as last
}, []);
console.log(result);
Кроме того, альтернативная реализация может быть выполнена просто с использованием регулярного выражения
/(?<=^|s)b.{1,15}b(?=s|$)/g
Это будет соответствовать до 15 символов, если они образуют целые слова, поэтому они не будут соответствовать середине слова или пробелам до или после слов.
const regex = /(?<=^|s)b.{1,15}b(?=s|$)/g;
const str = 'Lorem ipsum dolor sit amet consectetur adipiscing elit';
const result = [...str.matchAll(regex)].flat();
console.log(result);
Вот несколько примеров того, почему это работает:
Lorem ipsum dolor sit amet consectetur adipiscing elit
^ ^^ ^
|_________|| |
11 | |
| |
| -> the 15th character but the next symbol is not whitespace or the end of the line, so the match cannot end here
-> whitespace so the match cannot end here
Lorem ipsum dolor sit amet consectetur adipiscing elit
^^ ^
||____________|
| 14
|
-> the match cannot start on a whitespace and it also has to be preceded by whitespace