1

I have a string that I am splitting using string.split(' '); in order to turn the string into an array.

suppose I have these two tables, table1 and table2.

<table border="1" id="table1">
    <tr>
        <th colspan="2">Image One</th>
    </tr>
    <tr>
        <td style="width:40%;"><img src="airplane.jpg" alt="Image 1"></td>
        <td>
            <dl>
              <dt>airplane</dt>
              <dt>flight</dt>
              <dt>travel</dt>
              <dt>military</dt>
              <dt>word war</dt>
              <dt>GI</dt>
            </dl>
        </td>
    </tr>
</table>

<table border="1" id="table2">
    <tr>
        <th colspan="2">Image Two</th>
    </tr>
    <tr>
        <td style="width:40%;"><img src="apple.jpg" alt="Image 1"></td>
        <td>
            <dl id="tags">
              <dt>red</dt>
              <dt>apple</dt>
              <dt>round</dt>
              <dt>fruit</dt>
              <dt>healthy</dt>
              <dt>doctor</dt>
            </dl>
        </td>
    </tr>
</table>

right now for testing purposes I have an id of tags on table2's dl.

I am using a function to turn that DL (#tags) into an array

function getArray(id) {
var node, list, arrValue;

    array = [];
    for (node = document.getElementById(id).firstChild;
        node;
        node = node.nextSibling) {
        if (node.nodeType == 1 && node.tagName == 'DT') {
            array.push(node.innerHTML);
        }
    }
    console.log(array)
}

in order to check it against my original string to see if any of the values match. However, I am going to have multiple DT's that the string is going to be check against. Would it be correct to add all the tables into a 3d array and then check the values in the string against the 3d array? or is there a better approach?

UPDATE

The problem is:

I am eventually going to have tables filled with an image and tags. Essentially I want to be able to search those tags against my string (which will be separated into an array) then return the image with the most tags in the string. I am trying to figure out the best way to do that. Thank you

4

2 に答える 2

3

Rather than an array I would use an Object to store the list of tags, where the keys are the tags and the values are irrelevant.

This would give you O(1) lookup to check whether some other string exists in that list, as opposed to an O(n) lookup if you were using array.indexOf().

The function below will find every DT on the page and then return an object containing a map from each DT's text to the ID of its parent DL.

function makeMap() {
    var map = {};
    var dls = document.getElementsByTagName('DL');
    for (var i = 0, n = dls.length; i < n; ++i) {
        var dl = dls[i];
        var id = dl.id;
        var node = dl.firstChild;
        while (node) {
            if (node.nodeType == 1 && node.tagName == 'DT') {
                var tag = node.textContent || node.innerText; // latter for MSIE
                map[tag] = id;
            }
            node = node.nextSibling;
        }
    }
    return map;
}

Alternatively, in jQuery (with some pure JS mixed in for efficiency):

function makeMap2() {
    var map = {};
    var $dt = $('dl > dt');
    $dt.each(function() {
        var tag = this.textContent || this.innerText;
        map[tag] = this.parentNode.id;
    });
    return map;
}
于 2012-12-19T19:34:57.003 に答える
1

You wouldn't use a three-dimensional array, but only a two-dimensional one with tables and their tags. Or, as Alnitak already mentioned, even better a lookup object:

var map = {};
var dls = document.getElementsByTagName('dl');
for (var i = 0, i < dls.length; i++) {
    var tableid = dls[i].id; // identifier?
    var dts = dls[i].getElementsByTagName('dt'); // assuming you don't nest them
    for (var j = 0; j < dts.length; j++) {
        var text = dts[j].textContent || dts[i].innerText;
        var tags = text.split(/\s+/);
        for (var k=0; k<tags.length; k++)
            if (tags[k] in map)
                map[tags[k]].push(tableid);
            else
                map[tags[k]] = [tableid]; // an array
    }
}
/* now, map could look like this:
{
    word: ["table1"],
    war: ["table1"],
    red: ["table2"],
    double: ["table1", "table2"], // tags in more than one table
    …
}
*/

To get the table with the most tags in the string you now can use a function like this, which returns the respective tableids sorted by tag occurence:

function getHighestTables(string) {
    var tags = string.split(/\s+/);
    var tablecounts = {};
    for (var i=0; i<tags.length; i++) {
        var tables = map[tags[i]] || [];
        for (var j=0; j<tables.length; j++) {
            var tableid = tables[j];
            if (tableid in tablecounts)
                tablecounts[tableid]++;
            else
                tablecounts[tableid] = 1;
        }
    }
/*  tablecounts might now look like this:
    {
        table1: 2
        table2: 5
    }
*/
    return Object.keys(tablecounts).sort(function (a, b) {
        return tablecounts[b] - tablecounts[a];
    });
}
于 2012-12-19T20:15:41.590 に答える