gpt4 book ai didi

javascript - JS:将 bool 列表转换为紧凑字符串?

转载 作者:行者123 更新时间:2023-12-03 07:16:51 24 4
gpt4 key购买 nike

我在javascript中有大量的 bool(boolean) 值,并且希望将它们作为参数编码在url中,但不占用太多空间。所以我在想,是否可以将 bool(boolean) 数组转换为位数组,然后将这些位转换为字符串?

因此,例如,如果我的 bool(boolean) 值列表为:

[false, true, true, false, false, false, false, true]

然后以位为单位
[0, 1, 1, 0, 0, 0, 0, 1]

这是仅字母 a的二进制文件(至少根据 this而言)。

这样的事情可能吗?如果是这样,如何转换回来?

最佳答案

您可以使用 map :

console.log( [false, true, true].map(item => item ? 1 : 0).join("") );

但是 map 在Internet Explorer中无法正常运行。相反,我将使用一个简单的for循环:

var bools = [false, true, true];
for(var i = 0; i < bools.length; i++) bools[i] = bools[i] ? 1 : 0;
console.log(bools.join(""));

但是 super 酷的是,如果您可以使字符串比短于0和1的字符串更短。如果您可以将多个相同值的连续 bool(boolean) 值收缩为单个字符怎么办?所以 [true, true, true, true]只是 "4"而不是 "1111"吗?这就是我在创建此代码时采用并运行的想法:

var trueMultiples = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', 'A', 'S', 'D'];
var falseMultiples = ['0', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'm', 'n', 'b', 'p', 'x', 'c', 'v', 'F', 'G', 'H', 'J', 'K', 'L', 'Z', 'X', 'C', 'V', 'B', 'N', 'M'];

function encryptBools(bools) {
var str = "",
run = [];

for (var i = 0; i < bools.length; i++) {
if (run.length == 0 || run[run.length - 1] === bools[i]) {
//stack up successive trues or successive falses as a "run"
run.push(bools[i]);
} else {
//when the run ends, convert it to a trueMultiples or falseMultiples character
var encryptionSet = bools[i] ? falseMultiples : trueMultiples;
while (run.length > encryptionSet.length) {
//if it's too long to be a single character, use multiple characters
str += encryptionSet[encryptionSet.length - 1];
run = run.slice(0, run.length - encryptionSet.length);
}
str += encryptionSet[run.length - 1];
run = [bools[i]];
}
}

if (bools.length > 0) {
//for the last run, convert it to a trueMultiples or falseMultiples character
var encryptionSet = run[run.length - 1] ? trueMultiples : falseMultiples;
while (run.length > encryptionSet.length) {
//if it's too long to be a single character, use multiple characters
str += encryptionSet[encryptionSet.length - 1];
run = run.slice(0, run.length - encryptionSet.length);
}
str += encryptionSet[run.length - 1];
}

return str;
}

function decryptBools(str) {
var bools = [];

for (var i = 0; i < str.length; i++) {
if (trueMultiples.indexOf(str[i]) > -1) {
for (var j = 0; j <= trueMultiples.indexOf(str[i]); j++) {
bools.push(true);
}
} else if (falseMultiples.indexOf(str[i]) > -1) {
for (var j = 0; j <= falseMultiples.indexOf(str[i]); j++) {
bools.push(false);
}
}
}

return bools;
}

var bools = [true, false, false, false, false, false, true, true, true, true, false];
console.log("ORIGINAL:" + JSON.stringify(bools));

var encryptedBools = encryptBools(bools);
console.log("ENCRYPTED: " + encryptedBools);

var decryptedBools = decryptBools(encryptedBools);
console.log("DECRYPTED: " + JSON.stringify(decryptedBools));
trueMultiplesfalseMultiples是表示您拥有该值的连续 bool(boolean) 数的字符。例如, "3"指示3个连续的假,而 "s"指示3个连续的假。
最好的情况是,您可以将200个 bool(boolean) 值减少为7个字符长的字符串。最坏的情况是200个字符长。预期为100.497个字符。
我坚持使用基本的字母数字字符,但是如果需要,可以随意在混合中添加“-”,“_”和“〜”。他们是 safe for urls
更新
实际上,让我感到震惊的是,我们将 bool(boolean) 值转换为0和1的第一步使我们有了以下内容:
[1, 1, 0, 1]
在我看来,这与二进制数极为相似。如果我们将该数组连接在一起并获得 1101,然后将其切换为十进制表示法将其显示为 13怎么办?甚至更好的是,我们可以使用更高的底数(例如36)来将其读取为 d!能够像这样切换数字的基数是产生较小结果的一种了不起的方法!
现在,我知道您在想什么。如果开头有 false并且数字最终变成 001之类的怎么办?开头的 0将会丢失!好吧,别担心。我们可以将算法设置为始终在切换碱基之前在开头添加 1。这样,所有 0都将保持有效。
这里有一些限制。有200多个 bool(boolean) 值,这些人为的数字将是巨大的。实际上,JavaScript无法处理的太大。我们需要将其分解为可管理的块,然后将这些块连接在一起以获得结果。
旁注:我们可以进行更多工作,只是表示有多少个前导零,而不是强制前导1改善我们的最佳情况,但是我认为这实际上可能会损害我们的平均情况,所以我没有没错强制使用前导1会强制我们所有的完整块始终为 11字符长,这一事实为我们节省了额外的定界符。为什么搞砸了?
无论如何,这就是我最终得到的结果:

function compress(bools) {
var sections = [], MAX_SAFE_SECTION = 52;
for (var i = 0; i < bools.length; i++) {
if (i % MAX_SAFE_SECTION == 0) sections.push([]);
sections[Math.floor(i / MAX_SAFE_SECTION)][i % MAX_SAFE_SECTION] = bools[i] ? 1 : 0;
}
for (var i = 0; i < sections.length; i++) sections[i] = parseInt("1" + sections[i].join(""), 2).toString(36);
return sections.join("");
}

function expand(str) {
var sections = [];
while (str.length > 0) str = str.replace(sections[sections.length] = str.substring(0, 11), "");
for (var i = 0; i < sections.length; i++) sections[i] = parseInt(sections[i], 36).toString(2).substring(1);
var bools = sections.join("").split("");
for (var i = 0; i < bools.length; i++) bools[i] = bools[i] == "1";
return bools;
}


var bools = [true, false, false, false, false, false, true, true, true, true, false];
console.log("ORIGINAL:" + JSON.stringify(bools));

var compressedBools = compress(bools);
console.log("COMPRESSED: " + compressedBools);

var expandedBools = expand(compressedBools);
console.log("EXPANDED: " + JSON.stringify(expandedBools));

它需要一个由200个 bool(boolean) 值组成的数组,并将其始终切成42个字符串。
很好,但是您可能会问自己为什么我们只使用基数36?我们可以走得更高吗?答案是我刚使用36,因为它是JavaScript的 parseInt函数内置的最高数字。如果我们愿意添加自定义基本转换代码,我们可以提高更高的水平。 here有一个很好的答案,它提供了一个不错的基本转换功能,因此我将复制它们的功能并将其粘贴到此处以证明我的观点:

function convertBase(value, from_base, to_base) {
var range = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_'.split('');
var from_range = range.slice(0, from_base);
var to_range = range.slice(0, to_base);

var dec_value = value.split('').reverse().reduce(function(carry, digit, index) {
if (from_range.indexOf(digit) === -1) throw new Error('Invalid digit `' + digit + '` for base ' + from_base + '.');
return carry += from_range.indexOf(digit) * (Math.pow(from_base, index));
}, 0);

var new_value = '';
while (dec_value > 0) {
new_value = to_range[dec_value % to_base] + new_value;
dec_value = (dec_value - (dec_value % to_base)) / to_base;
}
return new_value || '0';
}

function compress(bools) {
var sections = [], MAX_SAFE_SECTION = 52;
for (var i = 0; i < bools.length; i++) {
if (i % MAX_SAFE_SECTION == 0) sections.push([]);
sections[Math.floor(i / MAX_SAFE_SECTION)][i % MAX_SAFE_SECTION] = bools[i] ? 1 : 0;
}
for (var i = 0; i < sections.length; i++) sections[i] = convertBase("1" + sections[i].join(""), 2, 62);
return sections.join("");
}

function expand(str) {
var sections = [];
while (str.length > 0) str = str.replace(sections[sections.length] = str.substring(0, 9), "");
for (var i = 0; i < sections.length; i++) sections[i] = convertBase(sections[i], 62, 2).substring(1);
var bools = sections.join("").split("");
for (var i = 0; i < bools.length; i++) bools[i] = bools[i] == "1";
return bools;
}


var bools = [true, false, false, false, false, false, true, true, true, true, false];
console.log("ORIGINAL:" + JSON.stringify(bools));

var compressedBools = compress(bools);
console.log("COMPRESSED: " + compressedBools);

var expandedBools = expand(compressedBools);
console.log("EXPANDED: " + JSON.stringify(expandedBools));

我们可以安全地使用此自定义功能设置基数为62。这意味着我们可以采用200个 bool(boolean) 值的数组并将其始终缩减为35个字符串。如果阵列中没有大量的顺序重复,您可能想改用此选项。这是我选择的算法。

关于javascript - JS:将 bool 列表转换为紧凑字符串?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59923537/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com