1

Using a previously answered SO question as a reference, I created a function that populates a dropdown list in my HTML doc from an existing javascript array.

Here's the HTML:

<fieldset>
    <legend>Choose action</legend>
        <p>Choose your action and click next</p><br />
            <select id="trigger"></select>
</fieldset>

Here's the Javascript:

var guns =
    [
        ["Smith and Wesson 500", "Revolver", "Full Frame", 50, "sada"], //model, type, frame, cal, trigger
        ["Glock 19", "Semi", "Compact", 9, "striker"],
        ["Smith and Wesson M and P Shield 9", "Semi", "Compact", 9, "striker"],
        ["Ruger Alaskan", "Revolver", "Full Frame", 44, "dao"],
        ["Ruger SR9", "Semi", "Compact", 9, "striker"],
        ["Desert Eagle", "Semi", "Full Frame", 50, "sada"],
        ["Smith and Wesson M and P Shield 40", "Semi", "Compact", 40, "striker"]
    ]   

var triggerDropdown = function(){
    var sel = document.getElementById('trigger');
    for (var i = 0; i < guns.length; i++) {
        var opt = document.createElement('option');
        opt.innerHTML = guns[i][4];
        opt.value = guns[i][4];
        sel.appendChild(opt);
        }
    };

My challenge:

Populate trigger without duplicates. Also, the solution must not require me to permanently change guns (I found a few other helpful SO posts, but most of them involve first removing duplicates from the array...in this case, I don't have the option).

Thank you!

Community
  • 1
  • 1
Remo Williams
  • 235
  • 6
  • 17
  • 1
    You say you can't change `guns`, but you can change a copy of it: `var gunsCopy = guns.slice(0)` (just don't modify any of the inner arrays, or you'll be changing `guns` too). Remove the duplicates from the copy, and use that to populate the dropdown. – bfavaretto May 08 '13 at 02:33

2 Answers2

2

You can create a separate array with just the triggers:

var triggers = function(guns) {
  var unique = {};

  return guns.reduce(function(current, item) {
    if (!(item[4] in unique)) {
      current.push(item[4]);
      unique[item[4]] = 1;
    }
    return current;
  }, []);
}(guns);

Demo

Then iterate over triggers as per normal.

See also: Array.reduce()

Ja͢ck
  • 170,779
  • 38
  • 263
  • 309
  • Short but quite inefficient, it's a lot better to use a lookup object and loop once. – plalx May 08 '13 at 02:42
  • @plalx Agreed and updated; looping over the `guns` array and immediately populating would be even better, but that answer has been given already :) – Ja͢ck May 08 '13 at 02:50
  • Way better now! The advantage of this one would be if the array has to be reused ;) However, I think it's a better practice to wrap a self-executing function in `()`. – plalx May 08 '13 at 02:58
1

When building the list, keep track locally of the keys you've already used:

var triggerDropdown = function(){

    var already = {};
    var sel = document.getElementById('trigger');
    for (var i = 0; i < guns.length; i++) 
    {
      var val = guns[i][4];

      if (! already[val]) 
      {
        var opt = document.createElement('option');
        opt.innerHTML = val;
        opt.value = val;
        sel.appendChild(opt);

        already[val] = true;
      }
    }
};
Paul Roub
  • 36,322
  • 27
  • 84
  • 93
  • This worked very well. I was going down this path while trying to figure it out, but kept falling all over myself. Exactly what I was looking for. Thanks Paul! – Remo Williams May 08 '13 at 02:42
  • 1
    @PaulRoub, Probably the best way, however you should have a look at JavaScript best practices http://dev.opera.com/articles/view/javascript-best-practices/. – plalx May 08 '13 at 02:45
  • @plalx Bookmarked--can't wait to read, and find out all the crap I've been doing wrong :). For real, thank you for the reference! – Remo Williams May 08 '13 at 02:50
  • There's Javascript best practices, and then there's "close enough to the original code to make the differences clear", which seemed more helpful in this case. – Paul Roub May 08 '13 at 02:53
  • @PaulRoub, It doesn't hurt to learn more than a single thing ;) But yeah, it is probably easier to understand without too many changes. – plalx May 08 '13 at 03:01
  • And to be clear - the Opera article is well worth reading, and on a good day I follow much of it in my own code. – Paul Roub May 08 '13 at 03:02