如何安全地将逗号分隔的字符串转换为数字数组

3

编辑:

为什么这不是一个重复的问题

这个问题特别地解决了一个问题,即使用Number(str)将空字符串以及任意数量的空格字符转换为0

看一下以下代码片段:

convertBtn.addEventListener('click', () => console.log(toArrayOfNumber(foo.value)))

const toArrayOfNumber = str => str.split(',').map(Number);
<input type="text" id="foo" value="1,2,4,-1" />
<button type="button" id="convertBtn">convert to array of numbers</button>

只要输入具有适当的,一切都正常。现在我想使它对以下值安全故障:
  • ,
  • , ,,
这里让我感到意外的是,Number(“”)Number(“ ”)都返回0(这不是我想要的,因为根据我的用例,我不希望将“”或任何数量的空格视为数字)。
所以我想出了这个:

convertBtn.addEventListener('click', () => console.log(toArrayOfNumber(foo.value)))

const toArrayOfNumber = str => str.split(',').filter(x => x.trim() !== "").map(Number);
<input type="text" id="foo" value="1,2,4,-1,,, ,, 11" />
<button type="button" id="convertBtn">convert to array of numbers</button>

这感觉很尴尬,我希望有一个显而易见且更好的解决方案,但我没有看到。


你可以做的一件事(半无关紧要)是使用.map(Number)来缩短你的映射,而不是使用回调函数(参数已经默认)。 - Sterling Archer
@SterlingArcher 感谢你的提示,我已经将它编辑到问题中了。 - connexo
1
我刚刚注意到你也可以使用数字进行过滤。arr = '1,2,4,-1,,, ,, 11'.split(',').filter(Number).map(Number); // ((5) [1, 2, 4, -1, 11] - Sterling Archer
1
@SterlingArcher 很不幸,isNaN(" ")返回的结果是false。同样的,isNaN("")也是如此。 - connexo
1
@HereticMonkey 我认为这是相关的,但不是完全重复 -- OP正在进行不规则字符串拆分,而不是询问如何将CSV字符串转换为数组(另外我们已经发现它不允许0)。 - Sterling Archer
显示剩余4条评论
4个回答

2

@KendallFrey的回答(他不愿意发表所以我在这里分享他的解决方案)

最初的回答:
'1,2,4,-1,,, ,, 11,0,0'.split(/[, ]+/).map(x=>+x)

你仍然可以使用.map(Number),但是x=>+x会少1个字节。
在控制台中的结果:(7) [1, 2, 4, -1, 11, 0, 0] 另一个正则表达式解决方案(不允许小数):/-?\d+/g

这很美妙,因为它只需要迭代一次。 - connexo

2
如果你只涉及整数,以下方法也适用。0将被保留,但空值将被删除。"Original Answer"翻译成"最初的回答"。
split(',').filter(num => !isNaN(parseInt(num))).map(Number);

示例

const str = '1,2,4,-1,,, ,0, 11';

console.log(str.split(',').filter(num => !isNaN(parseInt(num))).map(Number));


1

试试这个:

const value="-99,1,2,4,-1,,, ,0,, 11"
const toArrayOfNumber = str => str.split(',').map(num => num.trim() && Number(num)).filter(num => !Number.isNaN(num) && typeof num != 'string');

const nums = toArrayOfNumber(value);

nums.forEach(num => console.log(typeof num, num));

我们使用trim的结果来确定是否应将其处理为数字。如果不是,则只有一个string,会被过滤掉。

虽然这个方法可行,但我不认为它解决了我想要摆脱的繁琐问题。 - connexo

1

你也可以通过Array.reduce来实现,每次迭代时使用isNaN检查parseInt

let data = "1,2,4,-1,,, ,0, 11"

let r = data.split(',').reduce((r,c) => isNaN(parseInt(c)) ? r : [...r, +c],[])

console.log(r)

这样你只需要在拆分后一次迭代数组。同时,这将保留零并且仅删除非数字内容。

我喜欢这个仅迭代一次的部分,但我更喜欢非reduce解决方案,因为我发现当我几个月后回来阅读时,reduce更难以阅读。 - connexo
我很难同意你的观点,认为正则表达式比一个带有三元运算符的简单数组缩减更容易阅读。但既然你接受适合自己的答案,我也不能责怪你。干杯。 - Akrion

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接