2

I need help for this exercise:

Array methods

Implement the uncompletedNotes function which, given an array of notes, returns only the uncompleted notes. A note is considered completed if all todo present have the done flag set to true.

This is what I've done:

function uncompletedNotes(notes) {

  let result = []

  notes.forEach(element => {
    if (element.todos.done == false) {
      result.push(element);
    }
  });

  return result;

}

const notes = [{
    id: 1,
    description: 'Workout program',
    todos: [{
        id: 1,
        name: 'Push ups - 10 x 3',
        done: false
      },
      {
        id: 2,
        name: 'Abdominals - 20 x 3',
        done: true
      },
      {
        id: 3,
        name: 'Tapis Roulant - 15min',
        done: true
      }
    ]
  },
  {
    id: 2,
    description: 'Front-end Roadmap',
    todos: [{
        id: 1,
        name: 'Learn HTML',
        done: true
      },
      {
        id: 2,
        name: 'Learn CSS',
        done: true
      },
      {
        id: 3,
        name: 'Learn JavaScript',
        done: true
      },
      {
        id: 4,
        name: 'Learn Angular',
        done: true
      }
    ]
  }
]

const notesInProgress = uncompletedNotes(notes);
console.log('All notes: ', notes);
console.log('Notes In Progress: ', notesInProgress);

But it gives me an empty array result in Notes in Progress.

1
  • This should help, please try: notes.filter(n => n.todos.some(t => (t.done === false)));. Iterates over notes & finds some element in todos which has done set to false. Instead of t.done === false, one may also use !t.done. Commented Mar 14, 2022 at 12:40

7 Answers 7

5
function uncompletedNotes(notes) {
    return notes.filter(note => note.todos.filter(todo => !todo.done))
}
Sign up to request clarification or add additional context in comments.

3 Comments

Wouldn't it be better for the inner filter to be some? That way we can stop after the first and it doesn't need to build the resulting array for the inner call.
@JoachimSauer Yes, some can be used to optimize the execution.
find should also work.
2

The problem here is that the todos property of each notes is itself an array, ie there is no done property on todos. It may be useful to look at the array methods every or some (likely some), which will return true if any item in an iterable returns true for a given condition.

 function uncompletedNotes(notes) {
  
  let result = []
      
      notes.forEach(element => {
        if(element.todos.some(todo => todo.done === false)) {
          result.push(element);
        }
      });

   return result;

  }

Comments

1

Todos is also an array, so you'd have to iterate over that one as well

Comments

0

'todos' is an array as well. You need to iterate over it. One way to do that is to use the find function as shown below.

function uncompletedNotes(notes) {
  
  let result = []
  
  notes.forEach(element => {
    if(element.todos.find(todo => todo.done === false)) {
      result.push(element);
    }
  });

  return result;

}

const notes = [
  {
    id: 1,
    description: 'Workout program',
    todos: [
      {
        id: 1,
        name: 'Push ups - 10 x 3',
        done: false
      },
      {
        id: 2,
        name: 'Abdominals - 20 x 3',
        done: true
      },
      {
        id: 3,
        name: 'Tapis Roulant - 15min',
        done: true
      }
    ]
  },
  {
    id: 2,
    description: 'Front-end Roadmap',
    todos: [
      {
        id: 1,
        name: 'Learn HTML',
        done: true
      },
      {
        id: 2,
        name: 'Learn CSS',
        done: true
      },
      {
        id: 3,
        name: 'Learn JavaScript',
        done: true
      },
      {
        id: 4,
        name: 'Learn Angular',
        done: true
      }
    ]
  }
]

const notesInProgress = uncompletedNotes(notes);
console.log('All notes: ', notes);
console.log('Notes In Progress: ', notesInProgress);

Comments

0

For each notes iterate over the todos

  • for each todos
    • check if its 'done'==true
    • if all the 'done's are not true, then push the note to inProgress array.

Comments

0

Firstly! Nice exercise. Second i change only a little bit in you foreach loop. And use filter.

  notes.forEach(element => {
    const open = element.todos.filter(t => t.done === false)    
    result.push(...open)
  });

function uncompletedNotes(notes) {
  
  let result = []
  
  notes.forEach(element => {
    const open = element.todos.filter(t => t.done === false)    
    result.push(...open)
  });
  return result;
}

const notes = [
  {
    id: 1,
    description: 'Workout program',
    todos: [
      {
        id: 1,
        name: 'Push ups - 10 x 3',
        done: false
      },
      {
        id: 2,
        name: 'Abdominals - 20 x 3',
        done: true
      },
      {
        id: 3,
        name: 'Tapis Roulant - 15min',
        done: true
      }
    ]
  },
  {
    id: 2,
    description: 'Front-end Roadmap',
    todos: [
      {
        id: 1,
        name: 'Learn HTML',
        done: true
      },
      {
        id: 2,
        name: 'Learn CSS',
        done: true
      },
      {
        id: 3,
        name: 'Learn JavaScript',
        done: true
      },
      {
        id: 4,
        name: 'Learn Angular',
        done: true
      }
    ]
  }
]

const notesInProgress = uncompletedNotes(notes);
console.log('All notes: ', notes);
console.log('Notes In Progress: ', notesInProgress);

Comments

0

In your .forEach loop, you have this line:

if(element.todos.done == false) {

Since todos is an array, you would need to check whether any of the array todos have their done property set to false. There are a few ways you can do this, but the way I've implemented in the full code at the end is using the Array.filter method:

    let todos = element.todos.filter(todo => !todo.done);
    // If todos contains at least one task, it is incomplete...
    if (todos.length > 0) {
      // ... so add it to the result array (which we return shortly)
      result.push(element);
    }

See the full code below for example:

function uncompletedNotes(notes) {
  let result = []
  notes.forEach(element => {
    let todos = element.todos.filter(todo => !todo.done);
    if (todos.length > 0) {
      result.push(element);
    }
  });
  return result;
}

const notes = [{
    id: 1,
    description: 'Workout program',
    todos: [{
        id: 1,
        name: 'Push ups - 10 x 3',
        done: false
      },
      {
        id: 2,
        name: 'Abdominals - 20 x 3',
        done: true
      },
      {
        id: 3,
        name: 'Tapis Roulant - 15min',
        done: true
      }
    ]
  },
  {
    id: 2,
    description: 'Front-end Roadmap',
    todos: [{
        id: 1,
        name: 'Learn HTML',
        done: true
      },
      {
        id: 2,
        name: 'Learn CSS',
        done: true
      },
      {
        id: 3,
        name: 'Learn JavaScript',
        done: true
      },
      {
        id: 4,
        name: 'Learn Angular',
        done: true
      }
    ]
  }
]

const notesInProgress = uncompletedNotes(notes);
console.log('All notes:', notes);
console.log('Notes In Progress:', notesInProgress);

Comments

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.