나는 자바 스크립트에 엄청난 부울 목록이 있고 URL에 매개 변수로 인코딩하고 싶지만 너무 많은 공간을 차지하지 않습니다. 그래서 부울 배열을 비트 배열로 변환 한 다음 해당 비트를 문자열로 변환하는 것이 가능할까요?
예를 들어 내 부울 목록이 다음과 같다면
[false, true, true, false, false, false, false, true]
그런 다음 비트는
[0, 1, 1, 0, 0, 0, 0, 1]
이는 단지 문자의 이진 a
(적어도에 따라 이 ).
이와 같은 것이 가능합니까? 그렇다면 다시 변환하는 방법은 무엇입니까?
지도를 사용할 수 있습니다.
console.log( [false, true, true].map(item => item ? 1 : 0).join("") );
그러나지도는 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(""));
그러나 0과 1보다 더 짧은 문자열을 만들 수 있다면 정말 멋질 것입니다. 동일한 값의 여러 연속 부울을 단일 문자로 축소 할 수 있다면 어떨까요? 그래서 [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));
trueMultiples
그리고 falseMultiples
그 값을 가진 연속적인 부울의 수를 나타내는 문자입니다. 예를 들어 "3"
는 3 개의 연속 참을 나타내고 3 개의 연속 거짓을 "s"
나타냅니다.
최상의 시나리오는 200 개의 bool을 7 자 길이의 문자열 로 줄일 수 있습니다 . 최악의 시나리오는 200 자입니다. 예상 길이는 100.497 자입니다.
나는 기본적인 영숫자 문자를 고수했지만 원하는 경우 "-", "_"및 "~"를 혼합에 추가해도됩니다. URL에 대해 안전합니다 .
실제로 부울을 0과 1로 변환하는 첫 번째 단계는 다음과 같은 결과를 남깁니다.
[1, 1, 0, 1]
저에게는 이진수와 놀랍도록 비슷해 보입니다. 우리가 그 배열을 함께 결합하고 그것을 얻은 1101
다음 십진수 표기법으로 전환하여 표시하면 13
어떨까요? 또는 더 좋은 점은 36과 같이 더 높은 염기를 사용하여 그대로 읽도록 할 수 있습니다 d
! 이와 같이 숫자의 밑을 바꿀 수 있다는 것은 더 작은 결과를 생성하는 멋진 방법입니다!
이제 당신이 무슨 생각을하는지 알아요. false
처음에 '가 있고 숫자가 다음과 같으면 001
어떨까요? 선두 0
가 잃어 버릴 것입니다 !! 글쎄, 걱정마. 1
기본을 전환하기 전에 항상 시작 부분 에 a 를 추가하도록 알고리즘을 설정할 수 있습니다 . 이렇게하면 모든 0
의가 중요하게 유지됩니다.
여기에는 몇 가지 제한 사항이 있습니다. 200 개 이상의 부울을 사용하면 이러한 인위적인 수는 엄청날 것입니다. 사실 JavaScript가 처리하기에 너무 큽니다. 우리는 그것을 관리 가능한 덩어리로 나눈 다음 그 덩어리를 합쳐 결과를 얻어야합니다.
참고 : 우리는 최선의 시나리오를 개선하기 위해 선행 1을 강요하는 대신 선행 0이 몇 개 있는지 신호를 보내기 위해 더 많은 작업을 할 수 있지만 실제로 평균 사례 시나리오를 손상시킬 수 있다고 생각합니다. '티. 선행 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 개의 부울 배열을 가져와 일관되게 42 자 문자열로 줄입니다.
좋습니다.하지만 왜 우리가 36 루수로 갔는지 스스로에게 물어보실 수도 있습니다. 더 높이 갈 수 있을까요? 대답은 이미 JavaScript의 parseInt 함수에 내장 된 가장 높은 숫자이기 때문에 36 개를 사용했습니다 . 사용자 지정 기본 변환 코드를 추가 할 의향이 있다면 더 높은 수준으로 갈 수 있습니다. 여기 에 좋은 기본 변환 기능을 제공 하는 멋진 답변이 있으므로 해당 기능을 복사하여 여기에 붙여 넣어 내 요점을 증명할 것입니다.
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 개의 부울 배열을 가져와 일관되게 35 자 문자열로 줄일 수 있습니다. 배열에 순차 반복이 많지 않은 경우 대신이 옵션을 사용하는 것이 좋습니다. 제가 고른 알고리즘입니다.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다