0

I am working with a rest api which returns data as so

students = [{
  batch_id: 22
  id: 1
  image: null
  name: "a new batch student",
    attendance: [
      { id: 1, student_id: 1, batch_id: 22, absent_on: "2019-09-15", time: "09:26:23" },
      { id: 9, student_id: 1, batch_id: 22, absent_on: "2019-09-19", time: "00:00:00" }
    ]

},
{
  batch_id: 22
  id: 2
  image: null
  name: "a new batch student",
    attendance: [
      { id: 9, student_id: 2, batch_id: 22, absent_on: "2019-09-19", time: "00:00:00" }
    ]

},
{
  batch_id: 22
  id: 12
  image: null
  name: "a new batch student",
    attendance: []

}]````  

is there a way to search/find within the 'attendance' array that matches the date i specify e.g. absent on == 2019-09-19

can I convert the above array so that the attendance array within the students array looks something like this

students = [{
  batch_id: 22
  id: 1
  image: null
  name: "a new batch student",
    attendance: [
      { id: 9, student_id: 1, batch_id: 22, absent_on: "2019-09-19", time: "00:00:00" }
    ]

},
{
  batch_id: 22
  id: 2
  image: null
  name: "a new batch student",
    attendance: [
      { id: 9, student_id: 2, batch_id: 22, absent_on: "2019-09-19", time: "00:00:00" }
    ]

},
{
  batch_id: 22
  id: 12
  image: null
  name: "a new batch student",
    attendance: []

}]

Thank you for any help in advance

3
  • why do you want to convert the data? As far as data modelling goes the first version is likely superior as it avoids redundancy. Commented Sep 19, 2019 at 20:25
  • 1
    your first array looks just fine. students.filter(({attendance}) => attendance.filter(day => day.absent_on === date)) Should return you list of students absent on date Commented Sep 19, 2019 at 20:26
  • @zfrisch i would like to get if the student was absent on the given date Commented Sep 19, 2019 at 20:28

5 Answers 5

2
function absentStudents(date){
  return students
    .filter(({attendance}) => !!attendance.some(({absent_on}) => absent_on === date).length);
}

absentStudents('2019-09-19') Should return you list of students absent on 2019-09-19

Sign up to request clarification or add additional context in comments.

Comments

1

To get the exact expected data with all the students returned, and only the absent date if it was on 2019-09-19 you can do:

const students = [{
  batch_id: 22,
  id: 1,
  image: null,
  name: "a new batch student",
    attendance: [
      { id: 1, student_id: 1, batch_id: 22, absent_on: "2019-09-15", time: "09:26:23" },
      { id: 9, student_id: 1, batch_id: 22, absent_on: "2019-09-19", time: "00:00:00" }
    ]

},
{
  batch_id: 22,
  id: 2,
  image: null,
  name: "a new batch student",
    attendance: [
      { id: 9, student_id: 2, batch_id: 22, absent_on: "2019-09-19", time: "00:00:00" }
    ]

},
{
  batch_id: 22,
  id: 12,
  image: null,
  name: "a new batch student",
    attendance: []

}];

const studentsAbsentOnDate = students.map(student => ({
  ...student,
  attendance: student.attendance.filter((day) => day.absent_on === "2019-09-19"),
}));

console.log(studentsAbsentOnDate);

Comments

0

the goal is to look for the element "attendance" in every student object and filter it out, the key to filtering is the input data that you want. by using

  students[n].attendence.filter(data=> data.absent_on == INPUT)

for each student

example:

  var students = [{
  batch_id: 22,
  id: 1,
  image: null,
  name: "a new batch student",
    attendance: [
      { id: 1, student_id: 1, batch_id: 22, absent_on: "2019-09-15", time: "09:26:23" },
      { id: 9, student_id: 1, batch_id: 22, absent_on: "2019-09-19", time: "00:00:00" }
    ]

},
{
  batch_id: 22,
  id: 2,
  image: null,
  name: "a new batch student",
    attendance: [
      { id: 9, student_id: 2, batch_id: 22, absent_on: "2019-09-19", time: "00:00:00" }
    ]

},
{
  batch_id: 22,
  id: 12,
  image: null,
  name: "a new batch student",
    attendance: []

}];

var searchDate = "2019-09-19"

for (var i = 0 ; i <students.length;i++){
  students[i].attendance = students[i].attendance.filter( data => data.absent_on == searchDate );

}

1 Comment

it is better to explain your solution when you post an answer
0

Let me introduce you to Filter and Some.

Array.Filter() is a method to filter an array based on some condition. Filter loops over all elements in an array, and if they meet the condition they get added to the return value. The only argument you pass it is the function which will be called on each element. The function must return True or False for each member of the array.

Array.Some() is similar, but instead of returning a copy of all the elements that meet the condition, it will check the condition on each element, and if any return True, Array.Some() will return True. Its an elaborate way to check if any elements meet your condition, like a giant OR block.

students = [{
    batch_id: 22,
    id: 1,
    image: null,
    name: "a new batch student",
    attendance: [{
        id: 1,
        student_id: 1,
        batch_id: 22,
        absent_on: "2019-09-15",
        time: "09:26:23"
      },
      {
        id: 9,
        student_id: 1,
        batch_id: 22,
        absent_on: "2019-09-19",
        time: "00:00:00"
      }
    ]

  },
  {
    batch_id: 22,
    id: 2,
    image: null,
    name: "a new batch student",
    attendance: [{
      id: 9,
      student_id: 2,
      batch_id: 22,
      absent_on: "2019-09-19",
      time: "00:00:00"
    }]

  },
  {
    batch_id: 22,
    id: 12,
    image: null,
    name: "a new batch student",
    attendance: []

  }
]



// Return student if
//    student has an absence date
//       that matches this date
studentsAbsentOn = (students, date) => {
  return students.filter((student) => {
    return student.attendance.some((record) => {
      return record.absent_on === date
    });
  })
}

let absentStudents = studentsAbsentOn(students, "2019-09-19")
//returns the objects of both students absent on 2019-09-19

//Output to HTML
let studentNames = ""

for (let i = 0; i < absentStudents.length; i++) {
  studentNames += absentStudents[i].name;
  studentNames += ",\n"
}
document.getElementById("a").textContent += studentNames;
<p id="a"></p>

Comments

0

Answer:

You can do a filter of the student data that resolves any data that reports the date exists within the attendance record by using some.

  let searchAbsentDate = (data, date) => 
     data.filter(student => 
      student.attendance.some(record => 
        record.absent_on == date));

Example:

let students=[{batch_id:22,id:1,image:null,name:"a new batch student",attendance:[{id:1,student_id:1,batch_id:22,absent_on:"2019-09-15",time:"09:26:23"},{id:9,student_id:1,batch_id:22,absent_on:"2019-09-19",time:"00:00:00"}]},{batch_id:22,id:2,image:null,name:"a new batch student",attendance:[{id:9,student_id:2,batch_id:22,absent_on:"2019-09-19",time:"00:00:00"}]},{batch_id:22,id:12,image:null,name:"a new batch student",attendance:[]}];

let searchAbsentDate = (data, date) => 
     data.filter(student => 
      student.attendance.some(record => 
        record.absent_on == date));

console.log( searchAbsentDate(students, "2019-09-19") );


Dealing with Validation:

Although the above is really all you need to do what you're asking, it lacks validation and error handling. If that's important you might consider a long-hand function like:

function searchAbsentDate(data, date) {
// helper methods
   const isDateFormat = datestring => /\d{4}-\d{2}-\d{2}/.test(datestring),
   isNotString = s => !typeof s === "string",   
   noAttendance = student => !student.attendance || student.attendance.length === 0,
   invalidStudentAttendance = attendance => !Array.isArray(attendance),
   noAbsentDate = absentRecord => !absentRecord;

// determine date is in correct format
   if(isNotString(date) || !isDateFormat(date)) {
   throw Error("Improper Date Format");
   }
// determine data is array
   if(!Array.isArray(data)) { 
   throw Error("Student Records is not Array");
   }

// get results of filter
   let studentsAbsentOnDate = data.filter(function studentRecord(student, index) {

   // check if student has attendance records
     if(noAttendance(student)) return false;

   // determine if valid student record format
     if(invalidStudentAttendance(student.attendance)) { 
     throw Error(`Invalid Student Record Format At ${index}`);
    }
   // determine if student has absent date
     return student.attendance.some(function wasAbsentOnDate(record, _index) {

   // determine if valid attendance record format
     if(noAbsentDate(record.absent_on)) { 
       throw Error(`Invalid Attendance Record Format At Student:${index} Attendance Record:${_index}`);
     }
   // does attendance show absent on specified date
        return record.absent_on == date;
     });
   });
   // return any student records that match date
   return studentsAbsentOnDate;
}

Example:

let students=[{batch_id:22,id:1,image:null,name:"a new batch student",attendance:[{id:1,student_id:1,batch_id:22,absent_on:"2019-09-15",time:"09:26:23"},{id:9,student_id:1,batch_id:22,absent_on:"2019-09-19",time:"00:00:00"}]},{batch_id:22,id:2,image:null,name:"a new batch student",attendance:[{id:9,student_id:2,batch_id:22,absent_on:"2019-09-19",time:"00:00:00"}]},{batch_id:22,id:12,image:null,name:"a new batch student",attendance:[]}];

function searchAbsentDate( data, date ) {
	const isDateFormat = datestring => /\d{4}-\d{2}-\d{2}/.test( datestring ),
		isNotString = s => !typeof s === "string",
		noAttendance = student => !student.attendance || student.attendance.length === 0,
		invalidStudentAttendance = attendance => !Array.isArray( attendance ),
		noAbsentDate = absentRecord => !absentRecord;
	if ( isNotString( date ) || !isDateFormat( date ) ) {
		throw Error( "Improper Date Format" );
	}
	if ( !Array.isArray( data ) ) {
		throw Error( "Student Records is not Array" );
	}
	let studentsAbsentOnDate = data.filter( function studentRecord( student, index ) {
		if ( noAttendance( student ) ) return false;
		if ( invalidStudentAttendance( student.attendance ) ) {
			throw Error( `Invalid Student Record Format At ${index}` );
		}
		return student.attendance.some( function wasAbsentOnDate( record, _index ) {
			if ( noAbsentDate( record.absent_on ) ) {
				throw Error( `Invalid Attendance Record Format At Student:${index} Attendance Record:${_index}` );
			}
			return record.absent_on == date;
		} );
	} );
	return studentsAbsentOnDate;
}
    
console.log( searchAbsentDate(students, "2019-09-19") );


Alternate Code Style:

Alternatively to the above, and my personal preference, you can abstract the parts away( checking, error handling, transformations ) into additional helper methods.

This gives you the added flexibility in storing these parts separately for cleanliness/reuse if you'd like, but the goal is to streamline the execution of the function so that it's both readable and easy to maintain/change in the future.

I find this style to be particularly useful when dealing with Projects involving Vue, React, and other state/rendering focused libraries and frameworks.

function searchAbsentDate( students, date ) {
    /*
       HELPER METHODS
    */
    const 
    // FORMAT CHECK-> date
        isDateFormat = datestring => /\d{4}-\d{2}-\d{2}/.test( datestring ),
        isNotString = s => !typeof s === "string",
        isNotDate = potentialDate => ( isNotString( potentialDate ) || !isDateFormat ),
    // FORMAT CHECK-> student
        noAttendanceRecords = student => !student.attendance || student.attendance.length === 0,
        invalidStudentAttendanceRecords = attendance => !Array.isArray( attendance ),
    // FORMAT CHECK-> attendance record
        noAbsentDate = absentDate => !absentDate,
    // DATA TRANSFORMS 
        forAllAttendanceRecords = ( attendanceRecords, index ) => checkFn => attendanceRecords.some( checkFn( index ) ),
        filterRecords = students => filterFn => students.filter( filterFn ),
    // FILTERS
        ifAbsentOnDate = date => index => ( record, _index ) => {
            if ( noAbsentDate( record.absent_on ) ) err.throwMissingDate( index, _index );
            return record.absent_on == date;
        },
        forAbsenceOnDate = ( student, studentIndex ) => {
            if ( noAttendanceRecords( student ) ) return false;
            if ( invalidStudentAttendanceRecords( student.attendance ) ) err.throwInvalidStudentRecord();
            return forAllAttendanceRecords( student.attendance, studentIndex )( ifAbsentOnDate( date ) );
        },
    // ERROR HANDLERS
    err = {
        throwMissingDate( stu_i, ar_i ) {
            throw Error( "Invalid Attendance Record Format At Student:" + stu_i + "Attendance Record:" + ar_i );
        },
        throwInvalidStudentRecord( index ) {
            throw Error( "Invalid Student Record Format At " + index );
        },
        throwStudentRecordsFormat() {
            throw Error( "Student Records is not Array" );
        },
        throwDateFormat() {
            throw Error( "Improper Date Format" );
        }
    };
    /* 
       EXECUTION
    */
    if ( isNotDate( date ) ) err.throwDateFormat();
    if ( !Array.isArray( students ) ) err.throwStudentRecordsFormat();
    return filterRecords( students )( forAbsenceOnDate );
}

Example:

let students = [{ batch_id: 22, id: 1, image: null, name: "a new batch student", attendance: [{ id: 1, student_id: 1, batch_id: 22, absent_on: "2019-09-15", time: "09:26:23" }, { id: 9, student_id: 1, batch_id: 22, absent_on: "2019-09-19", time: "00:00:00" }] }, { batch_id: 22, id: 2, image: null, name: "a new batch student", attendance: [{ id: 9, student_id: 2, batch_id: 22, absent_on: "2019-09-19", time: "00:00:00" }] }, { batch_id: 22, id: 12, image: null, name: "a new batch student", attendance: [] }];

function searchAbsentDate( students, date ) {
   
    const 
        isDateFormat = datestring => /\d{4}-\d{2}-\d{2}/.test( datestring ),
        isNotString = s => !typeof s === "string",
        isNotDate = potentialDate => ( isNotString( potentialDate ) || !isDateFormat ),
    
        noAttendanceRecords = student => !student.attendance || student.attendance.length === 0,
        invalidStudentAttendanceRecords = attendance => !Array.isArray( attendance ),
    
        noAbsentDate = absentDate => !absentDate,
    
        forAllAttendanceRecords = ( attendanceRecords, index ) => checkFn => attendanceRecords.some( checkFn( index ) ),
        filterRecords = students => filterFn => students.filter( filterFn ),
    
        ifAbsentOnDate = date => index => ( record, _index ) => {
            if ( noAbsentDate( record.absent_on ) ) err.throwMissingDate( index, _index );
            return record.absent_on == date;
        },
        forAbsenceOnDate = ( student, studentIndex ) => {
            if ( noAttendanceRecords( student ) ) return false;
            if ( invalidStudentAttendanceRecords( student.attendance ) ) err.throwInvalidStudentRecord();
            return forAllAttendanceRecords( student.attendance, studentIndex )( ifAbsentOnDate( date ) );
        },
    
    err = {
        throwMissingDate( stu_i, ar_i ) {
            throw Error( "Invalid Attendance Record Format At Student:" + stu_i + "Attendance Record:" + ar_i );
        },
        throwInvalidStudentRecord( index ) {
            throw Error( "Invalid Student Record Format At " + index );
        },
        throwStudentRecordsFormat() {
            throw Error( "Student Records is not Array" );
        },
        throwDateFormat() {
            throw Error( "Improper Date Format" );
        }
    };
   
    if ( isNotDate( date ) ) err.throwDateFormat();
    if ( !Array.isArray( students ) ) err.throwStudentRecordsFormat();
    return filterRecords( students )( forAbsenceOnDate );
}

console.log( searchAbsentDate( students, "2019-09-19" ) );


Whew...

I know, I know. I wrote quite a lengthy answer to this simple question - I tend to get carried away! In any case, whether or not all of this was useful to you, I hope I was able to help at least a little bit!

Good luck!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.