#javascript #arrays #string #algorithm
#javascript #массивы #строка #алгоритм
Вопрос:
У меня есть массив строк, который выглядит следующим образом.
['white t-shirt', 'blue jeans', 'red hat', 'brown glasses'...]
Мне нужно как-то поместить эти строки в следующий текст с помощью запятых, но перед последним элементом вместо запятой мне нужно установить и . Что-то вроде этого:
«Ваша карточка включает в себя белую футболку, синие джинсы, красную шляпу и коричневые очки, которые вы можете перейти на страницу оформления заказа»
Поскольку я собираюсь получать эти элементы массива из серверной части, мне нужно каким-то образом сделать динамическую генерацию приведенной выше строки. Как это может быть достигнуто, если это возможно, без цикла?
Комментарии:
1. Поправьте меня, если я ошибаюсь, но AFAIK согласно грамматике английского языка, перед «и» все равно должна быть запятая.
2. @YuryTarabanko Нет, фиксированной политики нет, исследуйте «оксфордскую запятую».
Ответ №1:
без временно сохраненных ссылок, но с изменением исходного strings
массива …
const strings = ['white t-shirt', 'blue jeans', 'red hat', 'brown glasses'];
console.log(
[strings.pop(), strings.join(', ')].reverse().join(' and ')
);
console.log('mutated ... strings :', strings);
.as-console-wrapper { min-height: 100%!important; top: 0; }
без временно сохраненных ссылок и на этот раз без изменения исходного strings
массива …
const strings = ['white t-shirt', 'blue jeans', 'red hat', 'brown glasses'];
console.log(
[strings.slice(0, strings.length - 1).join(', '), ...strings.slice(-1)].join(' and ')
);
console.log('not mutated ... strings :', strings);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Ответ №2:
Вызывается часть Intl
API Intl.ListFormat
. Если вы хотите иметь правильное форматирование списка в соответствии с правилами локали, я бы посоветовал вам использовать его вместо ручного форматирования.
Например, перед «и» в указанном случае должна быть запятая.
const strings = ['white t-shirt', 'blue jeans', 'red hat', 'brown glasses'];
const formatter = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' });
console.log(formatter.format(strings));
const short = ['white t-shirt', 'blue jeans'];
console.log(formatter.format(short));
Комментарии:
1. : P grammarly.com/blog /…
2. @malarres CLDR считает, что он должен быть там 😉
3. Спасибо за ссылку и пример. Я не знал об этом. Кое-что узнал.
4. Лучшая идея, но ее нельзя использовать в daily praxi, поскольку этот API не поддерживается Safari.
5. @VladislavLadicky Можно использовать polyfil formatjs.io/docs/polyfills/intl-listformat хотя
Ответ №3:
Вы можете использовать slice
метод массива, чтобы сделать это просто.
const arr = ['white t-shirt', 'blue jeans', 'red hat', 'brown glasses'];
const result = arr.slice(0, arr.length - 1).join(', ') ' and ' arr.slice(-1)[0];
console.log(result);
Комментарии:
1. Array.prototype.splice возвращает массив. Смешивать строку с массивами и полагаться на неявное принуждение не является хорошей практикой.
Ответ №4:
strings = ['white t-shirt', 'blue jeans', 'red hat', 'brown glasses'];
lastString = strings.pop();
result = strings.join(', ') ' and ' lastString;
Комментарии:
1. Изменение исходного массива — это, по крайней мере, плохая практика.
2. Довольно сложно исправить с помощью какой-то сложной гиперболы, такой как, ммм, ourStrings = […strings] и работать с ourStrings.
3. Ммм, хорошо, вы также знаете о деструктурировании. И это то, что вы называете «эффективным решением»?
Ответ №5:
Решение с reduce
:
const arr = ['white t-shirt', 'blue jeans', 'red hat', 'brown glasses']
const showList = () => {
const OXFORD_COMMA=document.getElementById('oxford-comma').value;
console.log(arr.reduce((acc,item,i) => (i<arr.length-1)?acc ', ' item:acc OXFORD_COMMA ' and ' item));
}
<p> Do you want to apply Oxford Comma rule? </p>
<select id="oxford-comma">
<option value=",">Yes</option>
<option value="">No</option>
</select>
<button type="button" onclick="showList()">output to console</button>
ОБНОВЛЕНИЕ: теперь с опцией «Оксфордская запятая» благодаря @yuri-tarabanko 🙂
Комментарии:
1. Reduce возвращает массив. Я думаю, что это неподходящий метод для этой задачи.
2. «Метод reduce() выполняет функцию редуктора (которую вы предоставляете) для каждого элемента массива, в результате чего получается одно выходное значение». developer.mozilla.org/en-US/docs/Web/JavaScript/Reference /…
3. Неплохо. И? Использование метода reduce по-прежнему является самой слабой идеей здесь.
Ответ №6:
Это решение не изменяет ваш исходный массив, использует только строковые методы, поэтому не полагается на неявное принуждение, и оно очень хорошо поддерживается браузерами. Intl.ListFormat — лучшая идея, к сожалению, этот API не поддерживается ни Safari, ни Edge.
let items = [
'white t-shirt',
'blue jeans',
'red hat',
'brown glasses'
]
let strings = items
.join(', ')
.replace(/,s*([^,] )$/, ' and $1')
Комментарии:
1. Используя это регулярное выражение, вы можете изменять данные. Последний элемент, содержащий запятую, будет изменен. Также должны иметь значение разборчивость кода и производительность.
2. Изменить данные? Как? О чем ты говоришь? Ваш код может изменять данные — исходный массив, а не мой.
3. Если последним элементом является «brown, очки», вы будете вставлять и в неправильном месте, преобразовывая это в «brown и очки», уничтожая данные, поскольку этого нигде нет в исходных данных