0

I wish to retrieve hall and its length from the result. Unfortunately, I am not able to retrieve it out and it shows undefined.

These are data:

{
  "result": {
    "Hall 0": [
      {
        "lectureID": "1110000001",
        "startTime": "08:30:00",
        "endTime": "10:30:00"
      },
      {
        "lectureID": "1110000002",
        "startTime": "12:30:00",
        "endTime": "14:00:00"
      },
      {
        "lectureID": "1110000004",
        "startTime": "14:00:00",
        "endTime": "16:00:00"
      }
    ],

    "Hall 1": [
      {
        "lectureID": "1110000003",
        "startTime": "08:00:00",
        "endTime": "09:00:00"
      }
    ],
    "Hall 2": [
      {
        "lectureID": "1110000006",
        "startTime": "09:00:00",
        "endTime": "11:00:00"
      }
    ],
    "Hall 3": [
      {
        "lectureID": "1110000007",
        "startTime": "08:30:00",
        "endTime": "11:00:00"
      }
    ]

These are my codes to retrieve the elements in Hall and the hall.length :

 for (let i = 0; i < Object.keys(result).length; i++) {
        console.log("result: ",result[`Hall ${i}`]);  //this line shows undefined
        console.log(result[`Hall ${i}`].length);    //this line is undefined
        for (let j = 0; j < result[`Hall ${i}`].length; j++) {
            const lecture = result[`Hall ${i}`][j];
            const startTime = lecture.startTime;
            const endTime = lecture.endtime;
            earliestStartTime = Math.min(earliestStartTime, startTime);
            latestEndTime = Math.max(latestEndTime, endTime);
        }
    }

May I know how can I get the objects in result as well as the elements in Hall? Thank you so much!

wink
  • 57
  • 6
  • what is the `result` here? In provided json (which is incorrect) all the "Halls" are under "result" entry. If you assign the whole object to "result" variable then you need to use "result.result" to access your objects – Adassko Jul 16 '20 at 14:34
  • A good hint when showing data on Stack Overflow: use `console.log(JSON.stringify(obj, null, 2))`, then copy and paste the data into the question. Highlight it and click the `{}` button in the toolbar. – Heretic Monkey Jul 16 '20 at 14:34
  • Does this answer your question? [How can I access and process nested objects, arrays or JSON?](https://stackoverflow.com/questions/11922383/how-can-i-access-and-process-nested-objects-arrays-or-json) – Heretic Monkey Jul 16 '20 at 14:36
  • @HereticMonkey I have edited the codes, and the link that you provided doesn't work for this case. – wink Jul 16 '20 at 14:44
  • @Adassko the `result` here is a `{}` computed from API – wink Jul 16 '20 at 14:46
  • It works for all cases of getting data out of any level of hierarchy of data. – Heretic Monkey Jul 16 '20 at 14:47
  • @wink: it works fine when I test your code. Just use `result.result` instead of `result` probably. But it's not the best way to access elements, you're relying on fact that they are 0 indexed. Use `Object.entries(result.result)` instead which will produce an array of key and value. Here I even see that you use just the value so you can use `Object.values(...)`. Other than that - Math.min and Math.max will not work with strings – Adassko Jul 16 '20 at 14:49

3 Answers3

1

Find earliestStartTime and latestEndTime in your data. Math.min can't work with string, so you need to use custom comparison function compareTime. Use Object.values to iterate for each property and reduce to find min and max.

const toSeconds = time => {
    const a = time.split(':');
    return +a[0] * 60 * 60 + +a[1] * 60 + +a[2];
};

const compareTime = (a, b, direction) => {
    const a1 = toSeconds(a);
    const b1 = toSeconds(b);

    return direction ? (a1 > b1 ? a : b) : a1 < b1 ? a : b;
};

const result = {
    'Hall 0': [
        { lectureID: '1110000001', startTime: '08:30:00', endTime: '10:30:00' },
        { lectureID: '1110000002', startTime: '12:30:00', endTime: '14:00:00' },
    ],
    'Hall 1': [{ lectureID: '1110000003', startTime: '08:00:00', endTime: '09:00:00' }],
    'Hall 2': [{ lectureID: '1110000006', startTime: '09:00:00', endTime: '11:00:00' }],
    'Hall 3': [{ lectureID: '1110000008', startTime: '09:00:00', endTime: '12:00:00' }],
};

const res = Object.values(result).reduce(
    (acc, arr) => {
        arr.forEach(lecture => {
            const startTime = lecture.startTime;
            const endTime = lecture.endTime;
            acc.earliestStartTime = compareTime(acc.earliestStartTime, startTime, false);
            acc.latestEndTime = compareTime(acc.latestEndTime, endTime, true);
        });

        return acc;
    },
    {
        earliestStartTime: '25:00:00',
        latestEndTime: '00:00:00',
    },
);

console.log(res);
Nikita Madeev
  • 4,284
  • 9
  • 20
  • sorry, may i ask what is `{earliestStartTime: '25:00:00',latestEndTime: '00:00:00',},` this part for? – wink Jul 16 '20 at 15:27
  • @wink these are the initial (boundary) values for comparison and finding the maximum and minimum time. (second parameter for [reduce](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce)) – Nikita Madeev Jul 16 '20 at 16:53
  • alright! I have a better understanding now, thanks! – wink Jul 17 '20 at 01:16
1

Just use Object.values to access your values as you don't use the key anyway:

Object.values(result.result)
  .map(lectures => ({
    earliestStartTime: lectures.map(x => x.startTime).reduce((x, y) => x < y ? x : y),
    latestEndTime: lectures.map(x => x.endTime).reduce((x, y) => x > y ? x : y)
  }));

var result = {
  "result": {
    "Hall 0": [
      {
        "lectureID": "1110000001",
        "startTime": "08:30:00",
        "endTime": "10:30:00"
      },
      {
        "lectureID": "1110000002",
        "startTime": "12:30:00",
        "endTime": "14:00:00"
      },
      {
        "lectureID": "1110000004",
        "startTime": "14:00:00",
        "endTime": "16:00:00"
      }
    ],
    "Hall 1": [
      {
        "lectureID": "1110000003",
        "startTime": "08:00:00",
        "endTime": "09:00:00"
      }
    ],
    "Hall 2": [
      {
        "lectureID": "1110000006",
        "startTime": "09:00:00",
        "endTime": "11:00:00"
      }
    ],
    "Hall 3": [
      {
        "lectureID": "1110000007",
        "startTime": "08:30:00",
        "endTime": "11:00:00"
      }
    ]
  }
};

var times = Object.values(result.result)
    .map(lectures => ({
      earliestStartTime: lectures.map(x => x.startTime).reduce((x, y) => x < y ? x : y),
      latestEndTime: lectures.map(x => x.endTime).reduce((x, y) => x > y ? x : y)
    }));
    
console.log(times);
Adassko
  • 5,201
  • 20
  • 37
  • am i able to do a for-loop here to find the `earliestStartTime` and `latestEndTime`? – wink Jul 16 '20 at 15:26
  • sure, you can use `forEach`, `map` or `reduce` to iterate over objects. You can also use a normal for-loop or for-of loop `for (var sth of Object.values(result))` if you don't care about Internet Explorer. Experiment by yourself or you will need to come here with every problem – Adassko Jul 16 '20 at 15:36
  • Thank you so much! did lots of try of error yesterday and explored new stuff! – wink Jul 17 '20 at 01:17
1

You seems to have trouble to loop over object/array, i suggest you to restart javascript basis, and look at the example below

var object = {
  "result": {
    "Hall 0": [
      {
        "lectureID": "1110000001",
        "startTime": "08:30:00",
        "endTime": "10:30:00"
      },
      {
        "lectureID": "1110000002",
        "startTime": "12:30:00",
        "endTime": "14:00:00"
      },
      {
        "lectureID": "1110000004",
        "startTime": "14:00:00",
        "endTime": "16:00:00"
      }
    ],

    "Hall 1": [
      {
        "lectureID": "1110000003",
        "startTime": "08:00:00",
        "endTime": "09:00:00"
      }
    ],
    "Hall 2": [
      {
        "lectureID": "1110000006",
        "startTime": "09:00:00",
        "endTime": "11:00:00"
      }
    ],
    "Hall 3": [
      {
        "lectureID": "1110000007",
        "startTime": "08:30:00",
        "endTime": "11:00:00"
      }
    ]}};

var result = object.result;

for (var i in result) {
      console.log(i);
      console.log(result[i]);  //this line shows undefined
      console.log(result[i].length);    //this line is undefined
      for (let j = 0; j < result[i].length; j++) {
          const lecture = result[i][j];
          console.log(lecture);
      }
  }

Or if you just want the result without understanding anything

var object = {
  "result": {
    "Hall 0": [
      {
        "lectureID": "1110000001",
        "startTime": "08:30:00",
        "endTime": "10:30:00"
      },
      {
        "lectureID": "1110000002",
        "startTime": "12:30:00",
        "endTime": "14:00:00"
      },
      {
        "lectureID": "1110000004",
        "startTime": "14:00:00",
        "endTime": "16:00:00"
      }
    ],

    "Hall 1": [
      {
        "lectureID": "1110000003",
        "startTime": "08:00:00",
        "endTime": "09:00:00"
      }
    ],
    "Hall 2": [
      {
        "lectureID": "1110000006",
        "startTime": "09:00:00",
        "endTime": "11:00:00"
      }
    ],
    "Hall 3": [
      {
        "lectureID": "1110000007",
        "startTime": "08:30:00",
        "endTime": "11:00:00"
      }
    ]}};


    var result = Object.fromEntries(
        Object.entries(
           Object.values(object.result).flat().map(function(e){

              return {
                 startTime: new Date("2020-01-01T"+e.startTime+".000Z").getTime(), 
                 endTime: new Date("2020-01-01T"+e.endTime+".000Z").getTime()};
              }

           ).reduce(function(acc, e){

             acc.earliestStartTime = Math.min(acc.earliestStartTime || e.startTime, e.startTime);
             acc.latestEndTime = Math.max(acc.latestEndTime || e.endTime, e.endTime);
             return acc;
           },
           {earliestStartTime: null, latestEndTime: null}
           )
         ).map(function(e){
           e[1] = new Date(e[1]).toJSON().substr(11, 8);
           return e;
         })
     )
    console.log(result);
Daphoque
  • 4,421
  • 1
  • 20
  • 31
  • yep! this looks fine! But still I will not able to find the `earliestStartTime` and `latestEndTime` if i use my code in this for-loop – wink Jul 16 '20 at 15:28
  • You just have to add your logic, we're here to help, not to do the work :) – Daphoque Jul 16 '20 at 18:11
  • + you can't compare string time with just a Math.min, just try Math.min("11:00:00", "11:00:01") you will see that you're result is not valid, convert your time to a date object – Daphoque Jul 16 '20 at 18:13