66

我想要的是类似的东西Array.join(separator),但它需要第二个参数Array.join(separator, beforeLastElement),所以当我说[foo, bar, baz].join(", ", " or")我会得到时"foo, bar or baz"。我想我可以编写一个用于Array.slice分离最后一个元素的函数,但是有没有一些我可以使用的众所周知的方法呢?

4

15 回答 15

98

没有预定义的函数,因为它非常简单。

var a = ['a', 'b', 'c'];
var str = a.slice(0, -1).join(',')+' or '+a.slice(-1);

这种函数的主要用例也存在规范问题,即自然语言格式化。例如,如果我们使用牛津逗号逻辑,我们将得到与您正在寻找的结果不同的结果:

// make a list in the Oxford comma style (eg "a, b, c, and d")
// Examples with conjunction "and":
// ["a"] -> "a"
// ["a", "b"] -> "a and b"
// ["a", "b", "c"] -> "a, b, and c"
exports.oxford = function(arr, conjunction, ifempty){
    let l = arr.length;
    if (!l) return ifempty;
    if (l<2) return arr[0];
    if (l<3) return arr.join(` ${conjunction} `);
    arr = arr.slice();
    arr[l-1] = `${conjunction} ${arr[l-1]}`;
    return arr.join(", ");
}

所以把这个问题放在用户态似乎更好。

于 2013-02-25T14:47:33.813 回答
78

我可以建议:

['tom', 'dick', 'harry'].join(', ').replace(/, ([^,]*)$/, ' and $1')
> "tom, dick and harry"
于 2018-03-14T23:07:59.590 回答
20

使用 reduce 的在线解决方案:

[1, 2, 3, 4, 5].reduce((text, value, i, array) => text + (i < array.length - 1 ? ', ' : ' or ') + value);

=> "1, 2, 3, 4 or 5"
于 2020-03-12T09:26:33.807 回答
19

不,这足够具体,您必须编写自定义函数。正如您所说,好消息是,一旦您使用Array.join了所有分隔符,最后一个分隔符将很容易更新。

于 2013-02-25T14:47:16.497 回答
16

以@dystroy 的回答为基础:

function formatArray(arr){
    var outStr = "";
    if (arr.length === 1) {
        outStr = arr[0];
    } else if (arr.length === 2) {
        //joins all with "and" but no commas
        //example: "bob and sam"
        outStr = arr.join(' and ');
    } else if (arr.length > 2) {
        //joins all with commas, but last one gets ", and" (oxford comma!)
        //example: "bob, joe, and sam"
        outStr = arr.slice(0, -1).join(', ') + ', and ' + arr.slice(-1);
    }
    return outStr;
}

示例用法:

formatArray([]);                //""
formatArray(["a"]);             //"a"
formatArray(["a","b"]);         //"a and b"
formatArray(["a","b","c"]);     //"a, b, and c"
formatArray(["a","b","c","d"]); //"a, b, c, and d"
于 2015-03-24T13:43:19.523 回答
7

2021年更新答案!

如果目标是在倒数第二个和最后一个元素(例如“and”或“or”)之间使用不同的分隔符,则可以使用Intl.ListFormat

它正是这样做的,你可以免费获得 i18n。

除 IE11 外,所有主流浏览器都支持它。

例子:

const vehicles = ['Motorcycle', 'Bus', 'Car'];

const formatter = new Intl.ListFormat('en', { style: 'long', type: 'conjunction' });
console.log(formatter.format(vehicles));
// expected output: "Motorcycle, Bus, and Car"

const formatter2 = new Intl.ListFormat('de', { style: 'short', type: 'disjunction' });
console.log(formatter2.format(vehicles));
// expected output: "Motorcycle, Bus oder Car"

于 2021-09-02T14:44:48.543 回答
6

功能版本:

/* 
 * @param {Array.<string>} arr data array
 * @param {string} s1 regular separator
 * @param {string} s2 last separator
 */
function customJoin(arr, s1, s2) {
  return arr.slice(0,-1).join(s1).concat(arr.length > 1 ? s2 : '', arr.slice(-1));
}

function customJoin(arr, s1, s2) {
  return arr.slice(0, -1).join(s1).concat(arr.length > 1 ? s2 : '', arr.slice(-1));
}

const arr1 = ['a','b','c','d'];
const arr2 = ['singleToken'];

console.log(customJoin(arr1, ',', ' and '));        // 'a,b,c and d'
console.log(customJoin(arr1, '::', ' and then::')); // 'a::b::c and then::d'
console.log(customJoin(arr2, ',', 'and '));         // 'singleToken'

于 2019-01-07T11:37:49.173 回答
6
Array.prototype.join2 = function(all, last) {
    var arr = this.slice();                   //make a copy so we don't mess with the original
    var lastItem = arr.splice(-1);            //strip out the last element
    arr = arr.length ? [arr.join(all)] : [];  //make an array with the non-last elements joined with our 'all' string, or make an empty array
    arr.push(lastItem);                       //add last item back so we should have ["some string with first stuff split by 'all'", last item]; or we'll just have [lastItem] if there was only one item, or we'll have [] if there was nothing in the original array
    return arr.join(last);                    //now we join the array with 'last'
}

> [1,2,3,4].join2(', ', ' and ');
>> "1, 2, 3 and 4"
于 2015-11-30T19:25:02.377 回答
4

有一个包连接数组

const join = require('join-array');
const names = ['Rachel','Taylor','Julia','Robert','Jasmine','Lily','Madison'];
const config = {
  array: names,
  separator: ', ',
  last: ' and ',
  max: 4,
  maxMessage:(missed)=>`(${missed} more...)`
};
const list = join(config); //Rachel, Taylor, Julia, (3 more...) and Madison
于 2017-11-16T12:55:36.813 回答
3

对我来说,最简单的解决方案是:

['1', '2', '3'].reduce((previous, current, index, array) => {
    if (index === array.length - 1) {
        return previous + ' & ' + current;
    } else {
        return previous + ', ' + current;
    }
})
于 2019-04-16T08:14:17.333 回答
3

虽然它的答案较晚,但添加了一些方法。

方法 1:使用 Array.splice() 添加last delimiter最后一个元素并加入和删除最后两个,

function join(arr,last)
{
    if(!Array.isArray(arr)) throw "Passed value is not of array type.";
    last = last || ' and '; //set 'and' as default
    
    (arr.length>1 && arr.splice(-1,0,last));
    arr = arr.join().split("");
    arr[arr.lastIndexOf(",")]="";
    arr[arr.lastIndexOf(",")]="";
    return arr.join("");
}

console.log( join([1]) ); //single valued array
console.log( join([1,2]) ); //double valued array
console.log( join([1,2,3]) ); //more than 2 values array,
console.log( join([1,2,3],' or ') ); //with custom last delimiter
console.log( join("name") ); //Non-array type

方法二:使用 Array.reduce() 通过遍历每个元素来构造字符串。

function join(arr,last)
{
    if(!Array.isArray(arr)) throw "Passed value is not of array type.";
    last=last||' and ';
    
    return arr.reduce(function(acc,value,index){
        if(arr.length<2) return arr.join();
        return acc + (index>=arr.length-2 ? index>arr.length-2 ? value : value+last : value+",");
    },"");
}

console.log( join([1]) ); //single valued array
console.log( join([1,2]) ); //double valued array
console.log( join([1,2,3]) ); //more than 2 values array,
console.log( join([1,2,3,4],' or ') ); //with custom last delimiter
console.log( join("name") ); //Non-array type

于 2018-07-05T13:57:05.600 回答
1

使用解构的解决方案:

const { log } = console;

const formatList = list => {
    const [last = "", ...rest] = [...list].reverse();
    return rest.length
       ? [last, rest.reverse().join(", ")].reverse().join(" and ")
       : last;
};

log(formatList([1, 2, 3, 4]));
log(formatList(["Me", "Myself", "I"]));
log(formatList(["", ""]));
log(formatList([42]));
log(formatList([]));

于 2021-09-20T15:15:30.450 回答
1
function getValuesfromArray(strArray) {
  let endString = "";

  if (strArray.length > 1) {
    const lastEntry = strArray.pop();
    endString = strArray.join(", ") + " or " + lastEntry;
  }
  else {
    endString = strArray.toString();
  }

  return endString;
}
于 2020-03-02T22:15:30.460 回答
1

非空数组的单行

arr.reduce((res, k, i) => [res, k].join(i  === arr.length - 1 ? ' or ' : ', '))
于 2021-03-30T19:18:44.363 回答
0

Denys Séguret 的牛津风格 join,但没有最后一个逗号:

function readableJoin(arr, conjunction = 'and', ifEmpty = '') {
  const length = arr.length;

  switch (length) {
    case 0:
      return ifEmpty;
    case 1:
      return arr[0];
    case 2:
      return arr.join(` ${conjunction} `);
    default:
      const arrCopy = arr.slice(0, -2);
      arrCopy.push(`${arr[length - 2]} ${conjunction} ${arr[length - 1]}`);
      return arrCopy.join(', ');
  }
}

readableJoin(['one', 'two', 'three']); // 'one, two and three'
于 2021-06-20T12:30:57.697 回答