Присоединяйтесь к массиву запятыми и "и"
Я хочу преобразовать массив ['one', 'two', 'three', 'four']
в one, two, three and four
Обратите внимание, что первые элементы имеют запятую, и, но есть слово and
между предпоследними один и последним.
Лучшее решение, которое я придумал:
a.reduce( (res, v, i) => i === a.length - 2 ? res + v + ' and ' : res + v + ( i == a.length -1? '' : ', '), '' )
Он основан на добавлении запятых в конце - за исключением второго последнего (a.length - 2
) и способа избежать последней запятой (a.length - 2
).
ОБЯЗАТЕЛЬНО должен быть лучший, аккуратный, более разумный способ сделать это?
Это сложная тема для поиска в поисковых системах, потому что она содержит слово "и"...
Ответы
Ответ 1
Один из вариантов будут pop
последний элемент, а затем join
все остальные запятыми, и сцепить с and
плюс последним пунктом:
const input = ['one', 'two', 'three', 'four'];
const last = input.pop();
const result = input.join(', ') + ' and ' + last;
console.log(result);
Ответ 2
Мне нравится подход Марка Мейера (и я бы поддержал его, если бы у меня был представитель), поскольку он не меняет входные данные. Вот мое вращение:
function makeCommaSeparatedString(arr, useOxfordComma) {
const listStart = arr.slice(0, -1).join(', ');
const listEnd = arr.slice(-1);
const conjunction = arr.length <= 1 ? '' :
useOxfordComma && arr.length > 2 ? ', and ' : ' and ';
return [listStart, listEnd].join(conjunction);
}
console.log(makeCommaSeparatedString(['one', 'two', 'three', 'four']));
// one, two, three and four
console.log(makeCommaSeparatedString(['one', 'two', 'three', 'four'], true));
// one, two, three, and four
console.log(makeCommaSeparatedString(['one', 'two'], true));
// one and two
console.log(makeCommaSeparatedString(['one']));
// one
console.log(makeCommaSeparatedString([]));
//
Ответ 3
Вы можете использовать Array.prototype.slice(), когда array.length
больше 1, и исключить остальные случаи:
const result = a => a.length > 1
? '${a.slice(0, -1).join(', ')} and ${a.slice(-1)}'
: {0: '', 1: a[0]}[a.length];
Пример кода:
const input1 = ['one', 'two', 'three', 'four'];
const input2 = ['A Tale of Two Cities', 'Harry Potter and the smth', 'One Fish, Two Fish, Red Fish, Blue Fish'];
const input3 = ['one', 'two'];
const input4 = ['one'];
const input5 = [];
const result = a => a.length > 1
? '${a.slice(0, -1).join(', ')} and ${a.slice(-1)}'
: {0: '', 1: a[0]}[a.length];
console.log(result(input1));
console.log(result(input2));
console.log(result(input3));
console.log(result(input4));
console.log(result(input5));
Ответ 4
Начиная с V8 v7.2 и Chrome 72, вы можете использовать приятный API Intl.ListFormat
. Он также позаботится о локализации вашего списка по запросу, что может быть очень полезно, если вам это нужно.
const lf = new Intl.ListFormat('en');
console.log(lf.format(['Frank']));
// → 'Frank'
console.log(lf.format(['Frank', 'Christine']));
// → 'Frank and Christine'
console.log(lf.format(['Frank', 'Christine', 'Flora']));
// → 'Frank, Christine, and Flora'
console.log(lf.format(['Frank', 'Christine', 'Flora', 'Harrison']));
// → 'Frank, Christine, Flora, and Harrison'
// You can use it with other locales
const frlf = new Intl.ListFormat('fr');
console.log(frlf.format(['Frank', 'Christine', 'Flora', 'Harrison']));
// → 'Frank, Christine, Flora et Harrison'
Ответ 5
Другим подходом может быть использование метода splice для удаления двух последних элементов массива и объединения их с помощью токена and
. После этого, вы можете нажать этот результат снова на массиве, и, наконец, объединить все элементы, используя ,
разделитель.
Обновлено:
1) Покажите, как это работает для нескольких случаев (не требуется никакого дополнительного контроля над длиной массива).
2) Оберните логику внутри метода.
3) Не изменяйте исходный массив (если не требуется).
let arrayToCustomStr = (arr, enableMutate) =>
{
// Clone the received array (if required).
let a = enableMutate ? arr : arr.slice(0);
// Convert the array to custom string.
let removed = a.splice(-2, 2);
a.push(removed.join(" and "));
return a.join(", ");
}
// First example, mutate of original array is disabled.
let input1 = ['one', 'two', 'three', 'four'];
console.log("Result for input1:" , arrayToCustomStr(input1));
console.log("Original input1:", input1);
// Second example, mutate of original array is enabled.
let input2 = ['one', 'two'];
console.log("Result for input2:", arrayToCustomStr(input2, true));
console.log("Original input2:", input2);
// Third example, lenght of array is 1.
let input3 = ['one'];
console.log("Result for input3:", arrayToCustomStr(input3));
// Fourth example, empty array.
let input4 = [];
console.log("Result for input4:", arrayToCustomStr(input4));
// Plus example.
let bob = [
"Don't worry about a thing",
"Cause every little thing",
"Gonna be all right",
"Saying, don't worry about a thing..."
];
console.log("Result for bob:", arrayToCustomStr(bob));
.as-console-wrapper {
top: 0px;
max-height: 100% !important;
}
Ответ 6
Используя Array # lower:
['one', 'two', 'three', 'four'].reduce( (a, b, i, array) => a + (i < array.length - 1? ', ': ' and ') + b)
Ответ 7
В основном так же, как один из ответов pop()
выше, но вариант, если вы не хотите изменять исходный массив:
let arr = ['one', 'two', 'three', 'four']
let s = arr.slice(0,-1).join(', ') + " and " + arr.slice(-1)
console.log(s)
Ответ 8
Intl.ListFormat
- это именно то, что вы хотите. Несмотря на то, что в мае 2019 года поддерживаются только Chrome 72+ и Opera 60+, для других браузеров доступен полифилл: https://github.com/zbraniecki/IntlListFormat
const list = ['A', 'B', 'C', 'D'];
// With Oxford comma
const lfOxfordComma = new Intl.ListFormat('en', {
style: 'long',
type: 'conjunction'
});
console.log(lfOxfordComma.format(list)); // → A, B, C, and D
// Without Oxford comma
const lfComma = new Intl.ListFormat('en-GB', {
style: 'long',
type: 'conjunction'
});
console.log(lfComma.format(list)); // → A, B, C and D