我在javascript中有大量的布尔值,并希望将它们作为参数编码在url中,但不占用太多空间。所以我在想,是否可以将布尔数组转换为位数组,然后将这些位转换为字符串?
例如,如果我的布尔值列表是:
[false, true, true, false, false, false, false, true]
然后以位为单位
[0, 1, 1, 0, 0, 0, 0, 1]
[仅是字母a
的二进制文件(至少根据this)。
是否有可能这样?如果是的话,如何转换回来?
console.log( [false, true, true].map(item => item ? 1 : 0).join("") );
var bools = [false, true, true, false, false, false, false, true]
var str = bools.map(Number).join('') // array to string
var arr = str.split('').map(Number).map(Boolean) // string to array
console.log( str )
console.log( arr )
let a = [true, true, false, true];
console.log(a.map(x => (+x).toString())); // Array(4) [ "1", "1", "0", "1" ]
console.log(a.map(x => (+x).toString()).join("")); // "1101"
function decode(string) {
var bytes = atob(string).split('').map(char => char.charCodeAt(0));
var bits = [];
for (var i = 0; i < bytes.length; i++) {
var byte = bytes[i];
var temp = [];
for (var bit = 0; bit < 8; bit++) {
temp.unshift(byte & 1)
byte >>= 1;
}
bits = bits.concat(temp)
}
return bits.map(Boolean)
}
仅在布尔值列表的长度是8的倍数时才有效
const compressBools = (bools) =>
String (bools .length) + '~' +
btoa ( bools
.map (b => b ? '1' : '0')
.reduce (
([c, ...r], b, i) => (bools .length - i) % 8 == 0 ? [[b], c, ...r] : [[...c, b], ...r],
[[]]
)
.reverse ()
.map (a => a .join (''))
.map (s => parseInt(s, 2))
.map (n => String.fromCharCode(n))
.join ('')
)
.replace (/\+/g, '-')
.replace (/\//g, '_')
.replace (/\=/g, '.')
const expandBools = (s, [len, str] = s .split ('~')) =>
atob (str
.replace (/\./g, '=')
.replace (/_/g, '/')
.replace (/\-/g, '+')
)
.split ('')
.map (c => c .charCodeAt (0))
.map (s => Number (s) .toString (2) .padStart (8, '0'))
.flatMap (a => a .split (''))
.slice (-len)
.map (c => c == '1')
const arr = Array.from({length: 200}, _ => Math.random() < .5)
const compressed = compressBools (arr)
console .log (`Compressed String: "${compressed}"`)
const expanded = expandBools(compressed)
console .log (`Output matches: ${expanded.every((b, i) => b == arr[i])}`)