skip to Main Content

The array of objects I want to filter/search looks somewhat like this:

var array = [
 {  
    id: 62,
    title: "sometitle",
    text: „aaaaaaaaaaaaaaa“,
    keywords: ["other", "Party", "Shanghai"],
    read: false
},
{   
    id: 63,
    title: "othertitle",
    text: "bbbbbbbbbbbbbbbbbb",
    keywords: ["Party", "Shanghai", "Seo-Yeon"],
    read: false
},
{   
    id: 64,
    title: "againothertitle",
    text: "ccccccccccccccccccc",
    keywords: ["Chinesisch", "Alltag", "other"],
    read: false
}];

I want to select one random value of an object and filter the whole array to find other objects that share this one specific value – except for the current object of course. To be more precise I want to filter the array with one of the „keywords“. The current object should be spliced from the array.
Also underneath the current object I want to display buttons that each contain the title of the object that shares the keyword. When the user clicks on one oft he buttons the according object should be selected, shown, again sliced from array. Again one of this selected object’s keywords should be randomly selected to filter the rest of the array with.
This is what the implementation should look like:it looks right but doesnt behave right^^

This is the html:

<body>
    <div id="container-fluid">
        <h2 id="title"></h2>
        <div id="output"></div> 
        <div id="button-container"></div>
     </div>      
    <script type="text/javascript" src="src/js/snu.js"></script>
    <script type="text/javascript" src="src/js/index.js"></script>
</body>

And this the JS:

var startKeywords = [];
var btnContainer = document.getElementById('button-container');
var title = document.getElementById('title');
var output = document.getElementById('output');
var container = document.getElementById('container-fluid');
var result = [];
var nextSnusButtons = [];
var button = [];
//select a random SNU
var randomIndex = Math.floor(Math.random() * snus.length); 

(function first() {
    //showing the first random scene
    var start = snus[randomIndex];
    title.innerHTML = start.title;
    title.id = start.id;
    output.innerHTML = start.text;
    start.read = true;
    cache.push(start);

    startKeywords = start.keywords;

    var randomStartKeyIndex = Math.floor(Math.random() * startKeywords.length); 
    var randomStartKey = startKeywords[randomStartKeyIndex];

    //create a filter
    function filterNextSet(val){
        var randomValueKeyIndex = Math.floor(Math.random() * val.keywords.length);
        var randomValueKey = val.keywords[randomValueKeyIndex];
        if (randomStartKey === val.keywords[0] || randomStartKey ===val.keywords[1] || randomStartKey === val.keywords[2] || randomStartKey === val.keywords[3] && randomStartKey.read === false) {
            return val
        }
    }

    //apply filter
    result = snus.filter(filterNextSet);
    var resultFirst = result[0];
    var resultLastIndex = result.length -1;
    var resultLast = result[resultLastIndex];
    var resultRandomIndex = Math.floor(Math.random() * result.length); 
    var resultRandom = result[resultRandomIndex];

    //generate HTML
    if(resultFirst.id  || resultRandom.id  || resultLast.id) {
        nextSnusButtons.push(resultFirst, resultRandom, resultLast);
        nextSnusButtons.forEach(function(nextSnu) {
            button = document.createElement('button');
            button.id = nextSnu.id;
            button.innerHTML = nextSnu.title;
            btnContainer.append(button);
        });
    }
})();

I have been using plain javascript to solve this problem for days but I only find myself in Spghetti code. I feel like I am constnatly repeating stuff and that this is not gonna end. I would really appreciate your help! Should I use React instead??
Thank You very much in advance!

2

Answers


  1. Ok,

    Here a simple example of doing the first part (filtering the data).

    In this example at the end I’m just showing the match for every combo, in your case you can just call the getForArrayItem with your random number.

    var array = [
     {  
        id: 62,
        title: "sometitle",
        text: "aaaaaaaaaaaaaa",
        keywords: ["other", "Party", "Shanghai"],
        read: false
    },
    {   
        id: 63,
        title: "othertitle",
        text: "bbbbbbbbbbbbbbbbbb",
        keywords: ["Party", "Shanghai", "Seo-Yeon"],
        read: false
    },
    {   
        id: 64,
        title: "againothertitle",
        text: "ccccccccccccccccccc",
        keywords: ["Chinesisch", "Alltag", "other"],
        read: false
    }];
    
    function getForArrayItem(idx) {
      let 
        item = array[idx],
        iset = new Set(item.keywords);
      return array.filter((i) => {
        //first don't include self
        if (i === item) return false;
        //now see if any of the keyword exist in this
        return i.keywords.some(x => iset.has(x));
      });
    }
    
    array.forEach((item, ix) => {
      console.log('ITEM ' + item.id + ' = ' +
         getForArrayItem(ix).map((i)=>i.id).join(', '));
    });

    Here is a snippet just using ES5 constructs. Also I’ve not used any forEach, some, filter.. just for loops..

    var array = [
     {  
        id: 62,
        title: "sometitle",
        text: "aaaaaaaaaaaaaa",
        keywords: ["other", "Party", "Shanghai"],
        read: false
    },
    {   
        id: 63,
        title: "othertitle",
        text: "bbbbbbbbbbbbbbbbbb",
        keywords: ["Party", "Shanghai", "Seo-Yeon"],
        read: false
    },
    {   
        id: 64,
        title: "againothertitle",
        text: "ccccccccccccccccccc",
        keywords: ["Chinesisch", "Alltag", "other"],
        read: false
    }];
    
    function getForArrayItem(idx) {
      var 
        item = array[idx],
        iset = {},
        ret = [],
        l;
      //first lets store a set of fast lookup keywords
      //we could use indexOf, but this should be faster
      for (l = 0; l < item.keywords.length; l++)
        iset[item.keywords[l]] = true;    
      //now loop through all arrays
      for (l = 0; l < array.length; l ++) {
        //lets not include our self
        if (l === idx) continue;
        var aitem = array[l], any = false;
        //now ltes see if any of keywords exist in our iset lookup
        for (var lc = 0; lc < aitem.keywords.length; lc++) {
          var keyword = aitem.keywords[lc];
          if (iset[keyword]) {
            ret.push(aitem);
            break;
          }
        }
        if (any) ret.push(item);
      }
      return ret;
    }
    
    for (var ix = 0; ix < array.length; ix ++) {
      var items = getForArrayItem(ix);
      var id_items = [];
      for (var ll = 0; ll < items.length; ll++) id_items.push(items[ll].id);
      console.log('ITEM ' + array[ix].id + ' = ' + id_items.join(', '));
    }
    Login or Signup to reply.
  2. This is my solution:

    function selectRandomKeyword(obj) {
      const max = obj['keywords'].length;
      const random = Math.floor(Math.random() * max);
      return obj['keywords'][random];
    }
    
    function findObjsWithKeyword(array, keyword) {
      const foundArray = [];
      array.forEach(obj => {
        if (obj['keywords'].includes(keyword)) {
          foundArray.push(obj);
        }
      });
      return foundArray;
    }
    
    const selectedObj = (array[0]);
    
    const keyword = selectRandomKeyword(selectedObj);
    
    const newObjs = findObjsWithKeyword(array, keyword);
    

    So newObjs will have your new array with only the matching randomly selected keyword. And if you want to remove the selectedObj:

    var index = newObjs.indexOf(selectedObj);
    
    newObjs.splice(index, 1);
    
    newObjs;
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search