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

9
  • This does not look like a good use case for <table>s Commented Dec 19, 2012 at 19:33
  • What do you mean by "3d array"? Also, please post your whole dl-to-array function. Commented Dec 19, 2012 at 19:34
  • so to recap: You are creating an array from a string, then you want to compare those array values with values already in a table on the page? Are you open to using jQuery? Commented Dec 19, 2012 at 19:34
  • 2
    @Eric: I can not see what you want to do with a 3 dimensional array. Please describe your problem, not what you think the solution would be. Commented Dec 19, 2012 at 19:43
  • 1
    So you have source array ['red', 'sky'] that needs to be checked against arbitrary number of arrays e.g. ['red', 'apple', 'round'], ['airplane', 'flight', 'travel'], ...? I see a 2d array, not 3d. Commented Dec 19, 2012 at 19:56

2 Answers 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;
}
Sign up to request clarification or add additional context in comments.

5 Comments

I guess the values should be the table(s) in which the tags are contained, as the OP seems to search for them.
@Bergi if you like, yes, if each tag can only appear in one table then you could use the values to indicate which one.
@Alnitak Could you give an example please?
@Alnitak Thanks for the update, however I am still slightly confused on how to implement it. What value do I give to the 'map' parameter? Also, I Would have to call this for every dl? say there are 100+
@Alnitak how would I view the values?
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];
    });
}

6 Comments

Thanks for your input, how would I use this with my html?
I moved everythign over to a jsfiddle jsfiddle.net/J4kF9 if you check the console, I am getting an error
Thanks for the hints, I fixed the bugs. Updated to jsfiddle.net/J4kF9/1, and the output says that there are more tags from the sentence found in table2 than in table1
Thank you very much, you helped helped me tremendously
Just out of curiosity how difficult would it be to edit this function for more than 2 tables
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.