【问题标题】:optimize boolean array size in json优化 json 中的布尔数组大小
【发布时间】:2018-02-24 07:32:02
【问题描述】:

我为类似塞尔达的游戏 (rpg) 编写了一个小型关卡设计器 无论是否在某个地方(从关卡设计器保存地图时,预先计算了可以行走的 16x16 方格) 然后将该地图加载到游戏中。

可行走的方块(瓦片)存储在大量数组 (x,y) 中

假设这是一个很小的 ​​3x3 地图,json 应该是这样的:

walls = [[true,true, true],
         [true,false,true],
         [true,true, true]]

意味着只有中心街区可以步行(1x1 不是墙 == false)

现在我确实使用布尔值来优化空间,从技术上讲,我可以在 1 个字节中存储 8 个块信息。

但它的存储方式现在感觉是未优化的,因为每个块都存储为 json 文件中布尔值的字符串表示形式。

有没有办法存储数组的原始二进制数据,或者创建我自己的协议并将这些不规则的二进制数据存储在 json 中?

这个数组在生成时显然不会被人类解释,所以我不介意它不可读。

【问题讨论】:

  • 您可以使用整数,只要您坚持 50 位左右。十六进制字符串会稍微不那么疯狂并且更接近可读(或至少是可格式化的)。
  • JSON 中没有二进制数据类型,但您可以将二进制值转换为十进制,或者更有效地转换为字符串,即每个字节一个字符。
  • 文森特,看看我的回答。它可以将这个特定的“墙”数组简化为:7|5|7,然后再将其转换回来。

标签: javascript arrays json typescript binary


【解决方案1】:

首先,让我们使用整数来代替:

walls = [[1,1,1],
         [1,0,1],
         [1,1,1]]

1 甚至看起来像一堵墙 ;-)

将它字符串化会给你一些比布尔值短得多的东西:

JSON.stringify(walls) // "[[1,1,1],[1,0,1],[1,1,1]]"

您也可以自己将地图字符串化为更紧凑的格式:

const walls = [[1,1,1],
             [1,0,1],
             [1,1,1]];

// Stringified
const map = walls.map(r => r.join('')).join('|');
console.log(map); // "111|101|111"

// Unstringified
const wallsAgain = map.split('|').map(r => r.split('').map(Number))
console.log(wallsAgain);

// Or back to your boolean format.
const wallsToBooleans = map.split('|').map(r => r.split('').map(c => c === '1'))
console.log(wallsToBooleans)

现在事情变得有趣了……

如果我们真的疯了,我们可以通过将1/0 的“二进制”表示转换为不同的基数来使字符串化映射更短:

const walls = [[1,1,1,1,1],
               [1,0,1,0,1],
               [1,1,1,1,1],
               [1,0,1,0,1],
               [1,1,1,1,1]];

const mapBase = 36;

const map = stringifyMap(walls);

console.log(map);                           // Stringified ("1f|15|1f|15|1f")
console.log(parseMap(map));                 // Unstringified
console.log(parseMap(map, c => c === '1')); // Or back to your boolean format.

// Walls to string
function stringifyMap(walls) {
  return walls.map(r => rowToStr(r)).join('|');
}

// String to walls
function parseMap(map, cellParser) {
  return map.split('|')
    .map(r => strToRow(r)
      .map(cellParser || Number))

}

function rowToStr(row){
  const num = parseInt(row.join(''), 2); // Parse the `'10101'` to int,
  return num.toString(mapBase);          // Then convert it to a higher base;
}

function strToRow(str){
  const num = parseInt(str, mapBase); // Parse the higher base to int,
  return num.toString(2).split('');   // Then convert it to binary.
}

【讨论】:

    猜你喜欢
    • 2013-02-01
    • 1970-01-01
    • 2016-08-16
    • 1970-01-01
    • 2018-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-12
    相关资源
    最近更新 更多