skip to Main Content

In my project I am moving from XML format to JSON format.
I have XML which consists from nodes like this:

<Creature>
    <Name>Someone</Name>
    <Desert>false</Desert>
    <Woods>false</Woods>
    <Mountains>false</Mountains>
    <Swamp>false</Swamp>
</Creature>

And the radio list with values equal to the tags names. Like this:

<input type="radio" name="creature_terrain" value="Desert" />Desert<br>

Old code filtered XML list by doing this:

let selector = 'Creature > ' + selectedTerrain + ':contains("true")';
var filteredCreatures = $(creaturesArray).find(selector).parent();

And so now I have JSON array:

  {
    "Name": "Someone",
    "Desert": false,
    "Woods": false,
    "Mountains": false,
    "Swamp": false
  }

But I can’t find a way to filter it as elegant as it was with XML. The only way I see is to switch/case. Any suggestions?

3

Answers


  1. If it actually is an array, you can use filter to go through looking for the matching terrain is true.

    EDIT: You could leave out the == true as it will evaluate it as boolean, but I prefer having it as its easier to read and understand.

    const creatures = [
      {
        "Name": "None",
        "Desert": false,
        "Woods": false,
        "Mountains": false,
        "Swamp": false
      },
      {
        "Name": "Swamp",
        "Desert": false,
        "Woods": false,
        "Mountains": false,
        "Swamp": true
      }
    ]
    
    const terrain = "Swamp";
    
    const creature = creatures.filter((e) => e[terrain] == true)
    
    console.log(creature)
    Login or Signup to reply.
  2. Try javascript native array methods like find or filter.

    const filteredCreatures = creaturesArray.filter(creature => creature.Desert);
    
    Login or Signup to reply.
  3. Assuming you have an array of objects rather than just one object you can use filter to filter out those object that match a specific condition.

    Let’s expand your example.

    1. There are two objects (I’ve lowercased the key names). One matches "desert" the other "swamp". There are corresponding radio inputs for demonstration.

    2. I’ve attached an event listener to the fieldset element to catch events from its children (event delegation).

    3. When a change event is fired the handler checks first to see if the element that fired the event was an radio button. Then it filters out the objects into a new array that match the "is the value of this object key true?" condition. We use the value of the changed radio button as the object key that we want to inspect.

    4. For convenience this filtered array of objects is displayed in an output element.

    const data=[{name:"Someone",desert:false,woods:false,mountains:false,swamp:true},{name:"Someone 2",desert:true,woods:false,mountains:false,swamp:false}];
    
    // Get the terrain and output elements
    const terrain = document.querySelector('.terrain');
    const output = document.querySelector('.output');
    
    // Add a listener to the terrain (fieldset) element
    terrain.addEventListener('change', handleInput);
    
    // When the terrain element catches an event
    function handleInput(e) {
    
      // It checks to see if its a corresponding
      // creature_terrain radio button
      if (e.target.matches('[name="creature_terrain"]')) {
        
        // Assigns the changed radio input's value to `key`
        const key = e.target.value;
    
        // And uses that key in the condition to filter
        // those objects where there is a match
        const filtered = data.filter(obj => obj[key]);
    
        // If there are objects in the filtered array
        // show them in the output element
        if (filtered.length) {
          output.textContent = JSON.stringify(filtered, null, 2);
        } else {
          output.textContent = '';
        }
      }
    }
    code { display: block; margin-top: 1rem; }
    <fieldset class="terrain">
      <legend>Terrain</legend>
      <input type="radio" name="creature_terrain" value="desert" />Desert
      <input type="radio" name="creature_terrain" value="swamp" />Swamp
    </fieldset>
    <pre><code class="output"></code></pre>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search