JavaScript:For循环自动构建多维数组

时间:2017-01-12 04:41:06

标签: javascript multidimensional-array nested cheerio

您好我在过去几个小时内一直在使用cheerio.js处理以下代码和非结构化内容。

到目前为止,我还没有成功,非常感谢你的帮助。

我正在迭代源内容以生成一个数组,只是输出数组的格式不正确。

以下是源HTML。

var cheerio = require('cheerio');
var htmlContent2 = '<div id="header1"><p class="headpara">Header content</p> <p class="elem"><b>a. </b>Lorem  dolor sit amet, consectetur:</p><p class="elem"><b>1. </b>Perferendis iure doloremque iusto  facilis.</p><p class="elem"><b>2. </b>Asperiores impedit officiis cumque molestias at rerum !</p><p class="elem"><b>b. </b>More dummy text.</p> <p class="elem"><b>1. </b>Additional dummy text: </p> <p class="elem"><b>(a).</b>Asperiores impedit officiis.</p> <p class="elem"><b>(b).</b>Lolestiae asperiores ad repellat est obcaecati.</p> <p class="elem"><b>2. </b>Lorem ipsum dolor sit amet 1.</p> <p class="elem"><b>3.</b>Lorem ipsum dolor sit amet 2. </p> <p class="notelem">Dignissimos maiores facere consequuntur quod.</p><p class="notelem"> maiores facere consequuntur quod.</p>  <p class="elem"><b>c. </b>Ea consectetur excepturi aperiam.</p></div>';

这是我的代码:

var $ = cheerio.load(htmlContent2);
//Regex to filter content based on pattern:

var regex1 = /[a-z]\.\s/,
    regex2 = /[0-9]\./,
    regex3 = /\([a-z]\)/,
    regex4 = /\([0-9]\)/;
allList = [];
var newElements = $(".elem b").filter(function () {
    var newList = [];    
    var item1,
    item2,
    item3,
    item4;
    newList.push($(this).parent().text());

    for (var i = 0, j = newList.length; i < j; i++) {
        if (regex1.test($(this).text())) {
            item1 = $(this).text();
           allList.push(item1);
        }
        if (regex2.test($(this).text())) {
            item2 = $(this).text();
            allList.push(item2);           
        }
        if (regex3.test($(this).text())) {
            item3 = $(this).text();
          allList.push(item3);   
        }
    }
});
console.log(JSON.stringify(allList));

目前的结果是:

["a. ","1. ","2. ","b. ","1. ","(a).","(b).","2. ","3.","c. "]

期望的结果应该是:

["a. ",["1. ","2. "],"b. ",["1. ",["(a).","(b)."],"2. ","3."],"c. "]

数组嵌套级别因源内容而异。我在论坛上搜索了类似的方法,但没有用。

由于

3 个答案:

答案 0 :(得分:1)

你越来越近了。只要你只需要测试你设置为正则表达式的4个条件,这应该可以正常工作。基本上,它只是检查你所处的级别,并从堆栈中推出或弹出一个数组来构建你想要的结构。

编辑:我清理了代码,因此不会污染您的范围。我也改变了你的正则表达式,有些是必要的,只是试图预测数据变化(即值之后没有空格或列表高于9)。

EDIT2 :我还注意到你试图对内容做些什么,所以我给你一种方法来嵌套一个对象的属性,这样你就可以获得有用的信息和嵌套“标签”。

EDIT3 :添加了一个打印功能,可以帮助您测试您遇到的问题并修复了一个错误,即从较高级别跳到下面的多个级别会错误地降低一个级别。您将看到我们拆分内容以便它可以嵌套标签,然后在输出期间按照您的意愿重新组合它们。这里只是记录,但当然可以很容易地将html标签附加到文档中。

var autoNest = function(list, prop) {

    var regex1 = /[a-z]\.\s?/,
        regex2 = /[0-9]+\.\s?/,
        regex3 = /\([a-z]\)\.\s?/,
        regex4 = /\([0-9]+\)\.\s?/;

    var getLevel = function(text) {
        if (regex1.test(text)) {
            return 0;
        }    
        if (regex2.test(text)) {
            return 1;        
        }
        if (regex3.test(text)) {
            return 2;
        }
        if (regex4.test(text)) {
            return 3;
        }
        throw new Error('Unexpected content');
    };

    var peek = function(arr) {
        return arr[arr.length - 1];
    };

    var result = [];
    var stack = [result];    
    var lastLevel = 0;

    list.forEach(function(obj) {
        var value = prop ? obj[prop] : obj;
        var currentLevel = getLevel(value);
        var arr = peek(stack);
        if (currentLevel > lastLevel) {
            var next = [];
            arr.push(next);
            stack.push(next);
        } else if (currentLevel < lastLevel) {
            var diff = lastLevel - currentLevel;
            for (var i = 0; i < diff; i++) {
                stack.pop();
            }
        }
        arr = peek(stack);
        arr.push(obj);
        lastLevel = currentLevel;
    });
    return result;
};

$('.elem b').each(function() {
    var label = $(this).text();
    var content = $(this).parent().text();
    items.push({
        label: label,
        content: content
    });
});

function printArray(items, level) {
    level = level || 0;
    items.forEach(function(item) {
        if (Array.isArray(item)) {
            printArray(item, level + 1);
        } else {
            var output = '';
            for (var i = 0; i < level; i++) {
                output += '  ';
            }
            output += item.label + ' ' + item.content;
            console.log(output);
        }
    });
}

var nested = autoNest(items, 'label');
printArray(nested);

答案 1 :(得分:0)

您的代码中只进行了一些编辑。我所做的不同是使用不同级别的不同数组:

var $ = cheerio.load(htmlContent2);
//Regex to filter content based on pattern:

var regex1 = /[a-z]\.\s/,
regex2 = /[0-9]\./,
regex3 = /\([a-z]\)/,
regex4 = /\([0-9]\)/;
allList = [];

//these should be here:
var level2 = [];
var level3 = [];


var newElements = $(".elem b").filter(function () {
var newList = [];    
var item1,
item2,
item3,
item4;
newList.push($(this).parent().text());
//var level2 = [];
//var level3 = [];  

for (var i = 0, j = newList.length; i < j; i++) {
    if (regex1.test($(this).text())) {

        if(level2.length > 0)
            {
            allList.push(level2);
            level2=[];
            }
        if(level3.length > 0)
            {
            level2.push(level3);
            allList.push(level2);
            level3=[];
            }

       item1 = $(this).text();
       allList.push(item1);
       continue;
    }


    if (regex2.test($(this).text())) {

        if(level3.length > 0)
            {
            level2.push(level3);
            level3=[];
            }


        item2 = $(this).text();
        level2.push(item2);
        continue;           
    }
    if (regex3.test($(this).text())) {


        item3 = $(this).text();
        level3.push(item3); 
        continue;
    }
   }
});
console.log(JSON.stringify(allList));

答案 2 :(得分:0)

Hi伙计们,这是我的解决方案,它会直接将a样式数组转换为b样式数组。

var a = ["a. ", "1. ", "2. ", "b. ", "1. ", "(a).", "(b).", "2. ", "3.", "c. "];
var b = ["a. ", ["1. ", "2. "], "b. ", ["1. ", ["(a).", "(b)."], "2. ", "3."], "c. "];
var level = function(o) {
    if (/[a-z]\.\s/.test(o))
        return 1;
    if (/[0-9]\./.test(o))
        return 2;
    if (/\([a-z]\)/.test(o))
        return 3;
    if (/\([0-9]\)/.test(o))
        return 4;
    return 0;
};
var shadow = function(arr) {
    var i, j, arr2 = [];
    for (i = 0, j = arr.length; i < j; i++) {
        arr2[i] = level(arr[i]);
    }
    return arr2;
};
var convert = function(arr) {
    var ia, ib, temp;
    var s = shadow(arr);

    if (arr.length > 1) {
        for (ia = 0, ib = 0; ia < arr.length; ia = ia + 2) {
            ib = s.indexOf(s[ia], ia + 1);
            if (ib > -1 && ib - ia > 1) {
                temp = arr.slice(ia + 1, ib);
                arr.splice(ia + 1, ib - ia - 1, convert(temp));
                s.splice(ia + 1, ib - ia - 1, []);
            }
        }
    }
    return arr;
};

测试:

let x = convert(a);
let txt =JSON.stringify(x);
ut.writeLog(txt);<br>
ut.assertEqual(x, b, joCompare);

测试开始 - (1) -
[&#34;一个。 &#34; [&#34; 1。 &#34;&#34; 2。 &#34],&#34; b。 &#34; [&#34; 1。 &#34; [&#34;(一)及#34;&#34;(B)&#34;。],&#34; 2。 &#34;&#34; 3&#34],&#34℃。 &#34;]
1. [通过] :( ...)==&gt; (Equal) - (Equal)预期为

- 测试结束 - (1) -

总计:1,通过:1,失败:0,统计:100%通过