Home > other >  Go to next or previous item if a key does not exist in an array
Go to next or previous item if a key does not exist in an array

Time:04-06

What I'm trying to achieve looks quite tricky to me. I want to move from one item to another which I am able to easily achieve with this code snippet as shown below.

Assuming I am having this array of Objects

const arr = [
{ answered: true, duration: 15 },  
{ answered: true, duration: 15 },
{ duration: 15 },
{ answered: true, duration: 15 },
{ duration: 15 },
];

Then I use this code snippet to achieve moving to the next item which works fine.

let count = 0;
arr[count   1];
return arr

However, What I am trying to achieve is move to the next item that doesn't have a answered: true key:value Meaning if I'm starting from the 0 index the next button should move to 3rd index because it doesn't have a answered: true

For more clarity, If I am able to get items that does not contain answered filtered out, I have to be able to do a count 1 that can also move me to the next array index in the filtered result.

Assuming the filtered result is

const filtered = [
{ duration: 15 },
{ duration: 15 },
]

I should be able to do filtered[count 1]

Thank you

CodePudding user response:

Assuming that both the iterator and the array are part of a global state, the function click() aims to simulate a button click that you mentioned.

The function loops through the array and starts searching for the next unanswered element, starting from the global iter value. The function sets the iter to be one after the current element that is not answered, so that when the function is called again, it starts searching from that next element.

The reset() function simply restarts the search again from the start.

let iter = 0

const arr = [{
    answered: true,
    duration: 15
  },
  {
    answered: true,
    duration: 15
  },
  {
    duration: 10
  },
  {
    answered: true,
    duration: 15
  },
  {
    answered: true,
    duration: 15
  },
  {
    answered: true,
    duration: 15
  },
  {
    answered: true,
    duration: 15
  },
  {
    duration: 3
  },
  {
    duration: 1
  },
];


const findNext = () => {
  for (let i = iter; i < arr.length; i  ) {
    if (!('answered' in arr[i]) || !arr[i].answered) {
      document.getElementById("resultIndex").innerHTML = `Result id: ${i}`;
      document.getElementById("result").innerHTML = `Result body: ${JSON.stringify(arr[i])}`;
      iter = i   1
      return
    }
  }
}

const reset = () => {
  iter = 0
  document.getElementById("resultIndex").innerHTML = `Result id: none`;
  document.getElementById("result").innerHTML = `Result body: none`;
}
<div>
  <button onClick={findNext()}>Next</button>
  <button onClick={reset()}>Reset</button>
</div>
<div>
  <div id='resultIndex'>Result id: none</div>
  <div id='result'>Result body: none</div>
</div>

CodePudding user response:

You should try something like this :

const arr = [
{ answered: true, duration: 15 },
{ duration: 15 },
{ answered: true, duration: 15 },
{ duration: 15 }
]
var i = 0
var missing

for (const element of arr) {
  if (!element.answered) { 
    missing = element
    break
  }
  i  
}

console.log(missing)
console.log(i)

CodePudding user response:

You can filter the array with elements that do not contain answered, then loop on them in the normal way.

var index = 0;

const arr = [
{ answered: true, duration: 15 },  
{ answered: true, duration: 15 },
{ duration: 15 },
{ answered: true, duration: 15 },
{ duration: 15 },
{ answered: true, duration: 15 },  
{ answered: true, duration: 15 },
{ duration: 15 },
{ answered: true, duration: 15 },
{ duration: 15 },
];

function findNext() {
  for (item in arr) {
    if (!arr[item].hasOwnProperty('answered')) {
      document.getElementById("index").setAttribute('value',item);
      break;
    }
  }
}
<button onClick="findNext()">Find next</button>

<input type="text" value="" id="index">

CodePudding user response:

Here's a reusable function:

findKeyValue(arr, 'answered', true)

On each object .flatMap() array method will compare a given key ("answered") and a given value (true) and returns the index number. It's not very clear as to the nature of this "button" so I guessed as to it's purpose and how it was made.

Details commented in example below

Note: The input array is altered to show functionality better.

const arr = [{
    answered: true,
    duration: 15
  },
  {
    duration: 15
  },
  {
    answered: true,
    duration: 15
  },
  {
    id: 'x'
  },
  {
    duration: 20,
    id: 'x'
  },
  {
    answered: true
  }
];

// Parameters and counter
let array = arr;
let key = 'answered';
let value = true;
let counter = 0;


function findKeyValue(array, key, value) {
  return array.flatMap((obj, idx) => obj[key] === value ? idx : []);
}

//console.log(findKeyValue(arr, 'answered', true));

//console.log(findKeyValue(arr, 'id', 'x'));

// Event handler binded to button
document.querySelector('button').onclick = incrementSkip;

// Event handler
function incrementSkip(e) {
  // [0,2,5]
  const indices = findKeyValue(array, key, value);
  // <ol> after the <button>
  const list = e.target.nextElementSibling;
  // All <li> of <ol>
  const items = list.children;
/*
items = [<li>,...<li>]
indices = [0,2,5]
counter = 0 index of indices -- next click will be 2
*/
items[indices[counter]].style.background = 'cyan';
  // increment counter by 1
  counter  ;
  /*
  if indices length is less than counter then start over at 0
  */
  if (counter > indices.length-1) counter = 0;
}
<button>click</button>
<ol>
  <li>I</li>
  <li>II</li>
  <li>III</li>
  <li>IV</li>
  <li>V</li>
  <li>VI</li>
</ol>

CodePudding user response:

If I am able to get items that [do] not contain answered filtered out ..... WISH GRANTED

  • filtered contains only objects that do not have answered = true
  • getNext() accepts the start index or count to use your words, and target array, and returns element of filtered at count 1
  • I notice that your indexing is 1-based but since array indices are zero-based in JavaScript my example sends -1 so that count 1 (the first index) is 0.

const arr = [
    { answered: true, duration: 15 },  
    { answered: true, duration: 15 },
    { duration: 15 },
    { answered: true, duration: 15 },
    { duration: 15 },
];

const filtered = arr.filter(({answered}) => answered);

//console.log( filtered );

function getNext(startIndex, array) {
     return array[startIndex 1]
}

console.log( getNext(-1, filtered) );

  • Related