我尝试从包含十六进制字节表示的字符串中提取字节值。该字符串还包含(未知)非十六进制字符,需要忽略(分隔符,空格格式)。
给定输入字符串"f5 df 45:f8 a 8 f53"
,结果将是数组[245, 223, 69, 248, 168, 245]
。请注意,字节值仅从两个十六进制数字输出(因此,忽略最后一个3
)。
作为附加约束,代码需要在ecmascript 3环境中工作。
到目前为止,我已经使用过这种方法:
function parseHex(hex){
hex = hex.replace(/[^0-9a-fA-F]/g, '');
var i,
len = hex.length,
bin = [];
for(i = 0; i < len - 1; i += 2){
bin.push(+('0x' + hex.substring(i, i + 2)));
}
return bin;
}
但是,我觉得有可能找到更优雅的解决方案,所以问题是:
这个问题是否有更好的解决方案(性能更好或用更少的代码解决问题)?
答案 0 :(得分:2)
由于您在我的原始答案的评论中提到您仅限于ES3,因此您应该能够这样做:
function parseHex(string) {
// remove all non-hex characters, and then separate them into an array in groups of 2 characters
var arr = string.replace(/[^0-9a-fA-F]/g, '').match(/[0-9a-fA-F]{2}/g);
// mutate the array in-place with the correct decimal values
for(var i = 0; i<arr.length; i++) {
arr[i] = parseInt(arr[i], 16);
}
return arr;
}
parseHex('f5 df 45:f8 a 8 f53'); // => [245, 223, 69, 248, 168, 245]
它基本上会执行map
所做的事情,除了它的空间复杂度低于map
,因为它会使数组发生变异。请参阅updated jsfiddle。
你可以这样做(这里是jsbin example):
'f5 df 45:f8 a 8 f53'.replace(/[^0-9a-fA-F]/g, '').match(/[0-9a-fA-F]{2}/g).map(function(hex) {
return parseInt(hex, 16);
});
// => [245, 223, 69, 248, 168, 245]
你可以使它成为这样的函数:
function parseHex(string) {
return string.replace(/[^0-9a-fA-F]/g, '').match(/[0-9a-fA-F]{2}/g).map(function(hex) {
return parseInt(hex, 16);
});
}
parseHex('f5 df 45:f8 a 8 f53');
基本上,您从字符串中删除非十六进制字符,然后匹配两个十六进制字符的组(根据您的要求)。 This answer描述了parseInt(hex, 16)
部分(反之为hex.toString(16)
)。
答案 1 :(得分:0)
使用正则表达式方法可以减少代码,但性能更差。非正则表达式解决方案可以提供更好的性能,代价是代码更多。
经过一些研究/谷歌搜索(并看到Josh Beams answer使用.match()
),我认为有几种可能的正则表达式方法可以改进原始方法。
直接使用.match()
(不含.replace()
),灵感来自Josh Beams answer:
function parseHex(hex){
hex = hex.match(/[\da-f]/gi);
for(var i = 0; i < hex.length - 1; i += 2){
hex[i >> 1] = +('0x' + hex[i] + hex[i + 1]);
}
hex.length = i >> 1;
return hex;
}
使用.replace()
进行迭代(受this启发):
function parseHex(hex){
var bin = [];
hex.replace(/([\da-f])[^\da-f]*([\da-f])/gi,
function(m, digit1, digit2){
bin.push(+('0x' + digit1 + digit2));
}
);
return bin;
}
循环使用.exec()
(也受this启发):
function parseHex(hex){
var bin = [],
regex = /([\da-f])[^\da-f]*([\da-f])/gi,
result;
while(result = regex.exec(hex)){
bin.push(+('0x' + result[1] + result[2]));
}
return bin;
}
在running performance tests here之后,所有正则表达式方法似乎都没有比原始方法更好的表现。出于好奇,我尝试了一种非正则表达式解决方案,它明显优于其他方法(代价略高一些):
function parseHex(hex){
var bin = [], i, c, isEmpty = 1, buffer;
for(i = 0; i < hex.length; i++){
c = hex.charCodeAt(i);
if(c > 47 && c < 58 || c > 64 && c < 71 || c > 96 && c < 103){
buffer = buffer << 4 ^ (c > 64 ? c + 9 : c) & 15;
if(isEmpty ^= 1){
bin.push(buffer & 0xff);
}
}
}
return bin;
}
我可能会选择非正则表达式。