基于多因素转换Javascript数组

基于多因素转换Javascript数组,javascript,arrays,parsing,statistics,Javascript,Arrays,Parsing,Statistics,这将是一个有点长的问题,但请容忍我,我会尽力解释它。 对于一个简单的统计练习,我尝试读取某个数据集,但是数据的格式非常奇怪。让我们从一个示例数据数组开始。数据在内部按8个区块编号组织 [101, 103, 253, 253, 253, 102, 104, 254, 73, 32, 100, 111, 110, 39, 116, 32, 107, 110, 111, 119, 32, 119, 104, 97, 116, 32, 105, 115, 32, 32, 32, 32, 254, 254

这将是一个有点长的问题,但请容忍我,我会尽力解释它。 对于一个简单的统计练习,我尝试读取某个数据集,但是数据的格式非常奇怪。让我们从一个示例数据数组开始。数据在内部按8个区块编号组织

[101, 103, 253, 253, 253, 102, 104, 254, 73, 32, 100, 111, 110, 39, 116, 32, 107, 110, 111, 119, 32, 119, 104, 97, 116, 32, 105, 115, 32, 32, 32, 32, 254, 254, 101, 102, 254, 254, 254, 0]
在数据文件中,有几个案例和几个变量(在本案例中,有3个变量和3个案例。一个案例可以被视为问卷的“受访者”)

变量如下所示(只有一些值相关)

这意味着变量A将占用一个字节,变量B也将占用一个字节,变量C将占用三个字节(ceil(20/8))

如果一个值介于1和251之间,我需要使用“值-特定偏差”。在这种情况下,100'

截至目前,数据如下所示:

Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable C: 'I don't know what is'
Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable C: 'I don't know what is'
Case 2 Variable A: 2
Case 2 Variable B: 4
然而,并不是每个值都适合“一个字节”。例如,变量C是一个字符串变量,可能有多个字节。这就是输入
253
值的地方

253的值表示:“下一个8字节的块将是该变量的值”。253的多个值意味着该值将有多个块。在这种情况下,我们知道变量C需要3个字节。所有这3个字节都是value
253
,因此我们知道需要在这个块之后读取3个8字节的块

从数组的第8个元素开始,即:

[73, 32, 100, 111, 110, 39, 116, 32, 107, 110, 111, 119, 32, 119, 104, 97, 116, 32, 105, 115, 32, 32, 32, 32]
将其转换为字符串将为我们提供:

“我不知道是什么”

因此,此时的数据如下所示:

Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable C: 'I don't know what is'
Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable C: 'I don't know what is'
Case 2 Variable A: 2
Case 2 Variable B: 4
之后,我们继续数据。我们在最后253处停了下来,所以现在还有两个数字(102和104,意思是2和4)

此时,数据如下所示:

Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable C: 'I don't know what is'
Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable C: 'I don't know what is'
Case 2 Variable A: 2
Case 2 Variable B: 4
现在我们看到一个254的值。这意味着一个“空字符串”。请注意,变量C(当前变量)的长度为3字节。这个块中只剩下1个字节。所以我们需要跳过已经读取的块,在那里再读取两个字节。下一个街区是:

[254, 254, 101, 102, 254, 254, 254, 0]
这将使案例2变量C 254、254、254的值产生以下数据集:

Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable C: 'I don't know what is'
Case 2 Variable A: 2
Case 2 Variable B: 4
Case 2 Variable C: ''
Case 1 Variable A: 1 - (101)
Case 1 Variable B: 3 - (103) 
Case 1 Variable C: 'I don't know what is' (253, 253, 253 = read 3 blocks: [73, 32, 100, 111, 110, 39, 116, 32, 107, 110, 111, 119, 32, 119, 104, 97, 116, 32, 105, 115, 32, 32, 32, 32]
Case 2 Variable A: 2 - (102)
Case 2 Variable B: 4 - (104)
Case 2 Variable C: '' - (254, 254, 254)
Case 3 Variable A: 1 - (101)
Case 3 Variable B: 2 - (102)
Case 3 Variable C: '' - (254, 254, 254)
之后,我们还有一些值需要解释,使结束数据集:

Case 1 Variable A: 1
Case 1 Variable B: 3
Case 1 Variable C: 'I don't know what is'
Case 2 Variable A: 2
Case 2 Variable B: 4
Case 2 Variable C: ''
Case 1 Variable A: 1 - (101)
Case 1 Variable B: 3 - (103) 
Case 1 Variable C: 'I don't know what is' (253, 253, 253 = read 3 blocks: [73, 32, 100, 111, 110, 39, 116, 32, 107, 110, 111, 119, 32, 119, 104, 97, 116, 32, 105, 115, 32, 32, 32, 32]
Case 2 Variable A: 2 - (102)
Case 2 Variable B: 4 - (104)
Case 2 Variable C: '' - (254, 254, 254)
Case 3 Variable A: 1 - (101)
Case 3 Variable B: 2 - (102)
Case 3 Variable C: '' - (254, 254, 254)

用头做这件事似乎很容易。以程序化的方式来做这件事是我无法理解的。有人有什么想法吗?

我想你至少应该有三点建议:

curblock = 0; // current 8 byte block
ptr = 0; // byte in current 8 byte block
nextblock = 8; // next 8 byte block
还有两个函数readNumber()和readString(),它们根据这些指针从数组中读取数据,当然也会更新这些指针。提示:

... 
if(ch == 253) {
    // my_tostring() must be implemented
    str += my_tostring(data.slice(nextblock, nextblock+8));
    nextblock += 8;
}

...
ptr++;
if(ptr == 8) { ptr=0; curblock=nextblock; nextblock+=8; }

我不清楚如何将C的值转换为字符串,但这段代码将为您提供90%的实现方法:

function Reader(array){
    this.blocks = [];

    while(array.length){
        this.blocks.push(array.splice(0,8));
    }

    this._currentBlock = this.nextBlock();
}
Reader.prototype = {
    currentBlock: function(){
        if(!this._currentBlock.length){
            this._currentBlock = this.nextBlock();
        }
        return this._currentBlock;
    },
    readNext: function(count){
        count = count || 1;
        var output = [];

        while(count--){
            var value = this.currentBlock().shift();

            switch(value){
                case 253: value = this.nextBlock(); break;
                case 254: value = []; break;
                default : value = [value]; break;
            }

            output = output.concat(value);
        }

        return output;
    },
    nextBlock: function(){
        return this.blocks.shift();
    },
    peek: function(){
        return this._currentBlock[0];
    },
    buildCases: function(){
        var cases = [];

        do{
            var obj = {};
            var i = cases.length + 1;

            obj['Case ' + i + 'Variable A'] = this.readNext();
            obj['Case ' + i + 'Variable B'] = this.readNext();
            obj['Case ' + i + 'Variable C'] = this.readNext(3);

            cases.push(obj);
        }
        while(this.peek() !== 0);

        return cases;
    }
};

var reader = new Reader([101, 103, 253, 253, 253, 102, 104, 254, 73, 32, 100, 111, 110, 39, 116, 32, 107, 110, 111, 119, 32, 119, 104, 97, 116, 32, 105, 115, 32, 32, 32, 32, 254, 254, 101, 102, 254, 254, 254, 0]);
var cases = reader.buildCases();

我在“253的值意味着:'下一个8字节的块将是这个变量的值'”中失去了您。这对我来说意味着:读取253序列后面的三个8字节块,即102104254。我为什么要跳过这个?数据是按8字节块组织的。由于我们在读取253序列时处于第一个块中,这意味着:“读取第二、第三和第四个块”。他们在8字节的数据块上做了很多调整。块中的剩余数据会发生什么变化。例如,第一块是[101、103、253、253、253、102、104、254]。102、104和254发生了什么?没关系,我明白了。这正是我需要的,并且完全解决了问题!现在也完成了项目,非常感谢!哇,真漂亮。我看到您发现这个数据结构非常奇怪,以至于需要努力来驯服它。如我所见,必须将尾随的0添加到输入数组中,变量a不能是0。谢谢!在将每个案例读入数据结构(因此是peek)后,该算法在buildCases方法中检查0。它假设输入数据中没有异常。您的代码更简洁(更快)。稍后我可能会将两者合并,看看我能想到什么。