序列化多个重复的数组

时间:2017-04-18 13:55:45

标签: javascript arrays regex

所以我有一系列数组,每个数组都是2500长,我需要将它们序列化并存储在非常有限的空间内。

由于我有很多重复项,我想将它们剪切成类似下面的内容。

[0,0,0,0,2,7,3,3,0,0,0,0,0,0,0,0,0]
// to
[0x4,2,7,3x2,0x9]

我写了几个单行(利用Lodash'_.repeat)来转换为此模式,但转换为大多数/所有情况下似乎都不起作用。

let serialized = array.toString().replace(/((?:(\d)+,?)((?:\2+,?){2,}))/g, (m, p1, p2) => p2 + 'x' + m.replace(/,/g, '').length);

let parsed = serialized.replace(/(\d+)x(\d+),?/g, (z, p1, p2) => _.repeat(p1 + ',', +p2)).split(',');

我不知道为什么它不起作用。这可能是由于数组中的一些数字。眼球,最大的是4294967295,但超过90%只是0

我的RegEx中缺少什么阻止它正常工作?是否有一种更简单的方法让我无法看到它?

我非常有信心将它从序列化状态转换回来,只需要一只手就可以将它转移到状态。

5 个答案:

答案 0 :(得分:1)

直接简单的序列化:



let serialize = arr => {
    const elements = [];
    const counts = []
    let last = undefined;
    [0,0,0,0,2,7,3,3,0,0,0,0,0,0,0,0,0].forEach((el,i,arr)=>{
       if (el!==last) {
          elements.push(el);
          counts.push(1);
       } else {
          counts[counts.length-1]++;
       }
       last = el;
    })
    return elements.map((a,i)=>counts[i]>1?`${a}x${counts[i]}`:a).join(",");
};
console.log(serialize([0,0,0,0,2,7,3,3,0,0,0,0,0,0,0,0,0]));




<强>更新

纯功能序列化一个:

&#13;
&#13;
let serialize = arr => arr
  .reduce((memo, element, i) => {
    if (element !== arr[i - 1]) {
      memo.push({count: 1, element});
    } else {
      memo[memo.length - 1].count++;
    }
    return memo;
  },[])
  .map(({count, element}) => count > 1 ? `${count}x${element}` : element)
  .join(",");
console.log(serialize([0,0,0,0,2,7,3,3,0,0,0,0,0,0,0,0,0]));
&#13;
&#13;
&#13;

纯函数反序列化

&#13;
&#13;
const deserialize = str => str
  .split(",")
  .map(c => c.split("x").reverse())
  .reduce((memo, [el, count = 1]) => memo.concat(Array(+count).fill(+el)), []);
console.log(deserialize("4x0,2,7,2x3,9x0"))
&#13;
&#13;
&#13;

为避免在此逻辑中使用.reverse(),我建议您将序列化从4x0更改为0x4

答案 1 :(得分:0)

试试这个

&#13;
&#13;
var arr = [0,0,0,0,2,7,3,3,0,0,0,0,0,0,0,0,0];
var finalArray = []; //array into which count of values will go

var currentValue = ""; //current value for comparison
var tmpArr = [];  //temporary array to hold values
arr.forEach( function( val, index ){
 if ( val != currentValue && currentValue !== "" )
 {
   finalArray.push( tmpArr.length + "x" + tmpArr[0] ); 
   tmpArr = [];
 }
 tmpArr.push(val);
 currentValue = val;
});
finalArray.push( tmpArr.length + "x" + tmpArr[0] );

console.log(finalArray);
&#13;
&#13;
&#13;

没有临时数组的另一个版本

&#13;
&#13;
var arr = [0, 0, 0, 0, 2, 7, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var finalArray = []; //array into which count of values will go

var tmpCount = 0; //temporary variable to hold count
arr.forEach(function(val, index) {
  if ( (val != arr[ index - 1 ] && index !== 0 ) ) 
  {
    finalArray.push(tmpCount + "x" + arr[ index - 1 ] );
    tmpCount = 0;
  }
  tmpCount++;
  if ( index == arr.length - 1 )
  {
    finalArray.push(tmpCount + "x" + arr[ index - 1 ] );
  }
});

console.log(finalArray);
&#13;
&#13;
&#13;

答案 2 :(得分:0)

不要使用RegEx。只需使用常规逻辑。我推荐array.reduce来完成这项工作。

&#13;
&#13;
const arr1 = [0,0,0,0,2,7,3,3,0,0,0,0,0,0,0,0,0]
const arr2 = ['0x4','2','7','3x2','0x9'];

const compact = arr => {
  const info = arr.reduce((c, v) =>{
    if(c.prevValue !== v){
      c.order.push(v);
      c.count[v] = 1;
      c.prevCount = 1;
      c.prevValue = v;
    } else {
      c.prevCount = c.prevCount + 1;
      c.count[v] = c.count[v] + 1;
    };
    return c;
  },{
    prevValue: null,
    prevCount: 0,
    count: {},
    order: []
  });
  
  return info.order.map(v => info.count[v] > 1 ? `${v}x${info.count[v]}` : `${v}`);
}

const expand = arr => {
  return arr.reduce((c, v) => {
    const split = v.split('x');
    const value = +split[0];
    const count = +split[1] || 1;
    Array.prototype.push.apply(c, Array(count).fill(value));
    return c;
  }, []);
}

console.log(compact(arr1));
console.log(expand(arr2));
&#13;
&#13;
&#13;

答案 3 :(得分:0)

这是典型的减少工作。这是你的compress函数在O(n)时间完成..

var arr      = [0,0,0,0,2,7,3,3,0,0,0,0,0,0,0,0,0],
    compress = a => a.reduce((r,e,i,a) => e === a[i-1] ? (r[r.length-1][1]++,r) : (r.push([e,1]) ,r),[]);
console.log(JSON.stringify(compress(arr)));

答案 4 :(得分:-1)

由于此处的动机是减少存储数组的大小,因此请考虑使用类似gzip-js的内容来压缩数据。