在JavaScript中将十六进制数格式化为短UUID

27

我在JavaScript中有一个十六进制数字。为了显示的目的,我想要将字符串格式化为:

ffffffff-ffff-ffff
00000000-0000-01ff

(8个数字)-(4个数字)-(4个数字),前面用填充零补齐。

我一直试图编写自己的循环来将任意十六进制数格式化为该格式,但这似乎是 JavaScript 中已经可以使用的东西。

是否有内置的方法可以在 JavaScript 中格式化十六进制数?


很遗憾,JavaScript没有办法格式化这样的十六进制数字。但是请查看此链接(http://josscrowcroft.github.com/accounting.js/),也许有所帮助。 - Neq
7个回答

59
我会进行一个两步处理:
1)将数字转换为带前导零的16位十六进制数:
var i = 12345; // your number
var h = ("000000000000000" + i.toString(16)).substr(-16);

2) 添加破折号

var result = h.substr(0, 8)+'-'+h.substr(8,4)+'-'+h.substr(12,4);

15

针对knabar的回答:

如果你的数字确实是一个完整的64位长,那么你应该意识到JavaScript只有双精度浮点数,最高精度约为53位。例如:

var i = 0x89abcdef01234567; // a 64-bit constant
var h = ("000000000000000" + i.toString(16)).substr(-16); // "89abcdef01234800"

因此,您可能希望将其分成两个32位数字,并每次格式化8个数字。然后第二个警告出现:JavaScript在有符号的32位整数上执行按位运算,而此格式化代码无法处理负数。

var i = 0xffd2 << 16; // actually negative
var h = ("0000000" + i.toString(16)).substr(-8); // "0-2e0000"

由于需要格式化成十六进制的数字很可能是比特位操作的结果,所以代码可以进行调整以打印出二进制补码:

var i = 0xffd2 << 16; // actually negative
var h = ("0000000" + ((i|0)+4294967296).toString(16)).substr(-8); // "ffd20000"

这将生成任意正数和负数的整数部分的底部32位的十六进制表示。 这可能是您想要的(它大致相当于printf("%08x"))。 还有一些特殊情况:

var i = 1.5; // non-integers are rounded
var h = ("0000000" + ((i|0)+4294967296).toString(16)).substr(-8); // "00000001"

var i = -1.5; // rounding is towards zero
var h = ("0000000" + ((i|0)+4294967296).toString(16)).substr(-8); // "ffffffff"

var i = NaN; // not actually a number
var h = ("0000000" + ((i|0)+4294967296).toString(16)).substr(-8); // "00000000"

虽然 (i|0)+4294967296 可以充分将数字强制限制在范围内并转换为无符号数,但 i >>> 0 也可以实现这个目的,并且更加清晰易懂。 - aaaaaa123456789

14

ES6 版本

function toPaddedHexString(num, len) {
    str = num.toString(16);
    return "0".repeat(len - str.length) + str;
}

var hexStr = toPaddedHexString(12345, 16);

5
在ES2017中,padStart方法进一步简化了此操作。使用num.toString(16).padStart(len, "0")即可实现。 - Chris_F

7

有两个针对String的方法,分别为padStartpadEnd

const num = 15;
console.log(num.toString(16).padStart(2, "0")); // "0f"

const num = 15;
console.log(num.toString(16).padEnd(2, "0")); // "f0"

关于链接的额外信息: padStartpadEnd


2

总结

对于像 00000000-0000-01ff 这样的 ID

这是从 Adam Leggett 的答案中重写和缩短的版本。

function createID_8_4_4(s)
{
 return(1e16+s).slice(-16).replace(/^.{8}|.{4}(?!$)/g,'$&-')
 /*
     OR the version for easy understanding:
     return(1e16+s).slice(-16).match(/..../g).join('-').replace('-','')
     replace on the end replaces only first '-'
 */
}

console.log(createID_8_4_4('01ff')); //00000000-0000-01ff

对于像0000-0000-0000-01ff这样的ID

function createID_4_4_4_4(s)
{
 return(1e16+s).slice(-16).match(/..../g).join('-')
}

console.log(createID_4_4_4_4('01ff')); //0000-0000-0000-01ff


1

我认为在纯JavaScript中没有任何相关的内容,但是框架提供了这种方法,在ExtJS 3中实现方式如下:

    /**
     * Pads the left side of a string with a specified character.  This is especially useful
     * for normalizing number and date strings.  Example usage:
     * <pre><code>
var s = String.leftPad('123', 5, '0');
// s now contains the string: '00123'
     * </code></pre>
     * @param {String} string The original string
     * @param {Number} size The total length of the output string
     * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
     * @return {String} The padded string
     * @static
     */
    leftPad : function (val, size, ch) {
        var result = String(val);
        if(!ch) {
            ch = " ";
        }
        while (result.length < size) {
            result = ch + result;
        }
        return result;
    }

这只是一个填充函数,那么十六进制格式和破折号呢? - maerics

1
我假设由于hexwab的回答中所描述的限制,该数字已经以字符串形式存在。如果不是,请通过适当的机制将其转换为任意长度的十六进制字符串(称为str),然后执行以下步骤:

function format(str) {
  return (1e15+str).slice(-16).match(/^.{8}|.{4}/g).join('-');
}

console.log(format('723e9f4911'))


非常好的简短解决方案!(+) 我从你的答案中写了一个更短的版本。请看我的回答。 - Bharata
@Bharata 我喜欢高尔夫!我们来试试吧。我修改了我的答案。 - Adam Leggett

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