提问人:Merc 提问时间:12/21/2018 最后编辑:BergiMerc 更新时间:11/4/2021 访问量:21630
用逗号和“and”连接数组
Join an array by commas and "and"
问:
我想将数组转换为['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
肯定有一种更好、更整洁、更智能的方法来做到这一点吗?
这是一个很难在搜索引擎上搜索的话题,因为它包含“和”这个词......
答:
一个选项是最后一项,然后是其余的逗号,并与最后一项连接起来:pop
join
and
const input = ['one', 'two', 'three', 'four'];
const last = input.pop();
const result = input.join(', ') + ' and ' + last;
console.log(result);
如果无法改变输入数组,请改用,如果输入数组中可能只有一个项目,请先检查数组的长度:slice
function makeString(arr) {
if (arr.length === 1) return arr[0];
const firsts = arr.slice(0, arr.length - 1);
const last = arr[arr.length - 1];
return firsts.join(', ') + ' and ' + last;
}
console.log(makeString(['one', 'two', 'three', 'four']));
console.log(makeString(['one']));
评论
当大于 1 时,可以使用 Array.prototype.slice() 并排除其余情况:array.length
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));
评论
['A Tale of Two Cities', 'Harry Potter and the smth', 'One Fish, Two Fish, Red Fish, Blue Fish']
另一种方法是使用 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;
}
我喜欢 Mark Meyer 的方法,因为它不会改变输入。这是我的想法:
const 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([]))
//
从 V8 v7.2 和 Chrome 72 开始,您可以使用 sweet 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'
您甚至可以指定选项以使其中断并使用“or”而不是“and”,或者设置“3 英尺,7 英寸”等单位的格式。
在撰写本文时,它没有得到广泛的支持,因此您可能不想在任何地方使用它。
参考资料
Intl.ListFormat API - Google Developers
V8 版本 v7.2
评论
使用 Array#reduce:
['one', 'two', 'three', 'four'].reduce(
(a, b, i, array) => a + (i < array.length - 1 ? ', ' : ' and ') + b)
评论
heresHowToHandleOxfords.reduce( (a, b, i, array) => a + ( i < array.length - 1 ? ', ' : (array.length > 2 ? ', and ' : ' and ') ) + b)
Intl.ListFormat
正是您想要的。虽然 2019 年 5 月仅支持 Chrome 72+ 和 Opera 60+,但 polyfill 可用于其他浏览器: 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
评论
一种简单的方法是使用正则表达式在最后一个单词或带引号的字符串之前插入。在堆栈溢出上回答and
这是一个单行选项,类似于 Yosvel Quintero Arguelles 的答案,但在有三个或更多项目时提供牛津逗号。
let resultA4 = (list => list.length < 3 ? list.join(" and ") : [list.pop(), list.join(", ")].reverse().join(", and ")).call(this, ['one', 'two', 'three', 'four']);
let resultA2 = (list => list.length < 3 ? list.join(" and ") : [list.pop(), list.join(", ")].reverse().join(", and ")).call(this, ['one', 'two']);
let resultA1 = (list => list.length < 3 ? list.join(" and ") : [list.pop(), list.join(", ")].reverse().join(", and ")).call(this, ['one']);
let items = ['one', 'two', 'three', 'four'];
//If you can't mutate the list you can do this
let resultB = (list => list.length < 3 ? list.join(" and ") : [list.pop(), list.join(", ")].reverse().join(", and ")).call(this, items.slice());
// or this option that doesn't use call
let resultC = items.length < 3 ? items.join(" and ") : [items.slice(0, -1).join(", "), items.slice(-1)].join(", and ");
console.log(resultA4);
console.log(resultA2);
console.log(resultA1);
console.log(resultB);
console.log(resultC);
评论
上一个:使用节点的内置调试器检查变量?
评论
one, two, three, and four