0

I want to sort my JSON by date, and if there are multiple entries for a specific date, group all of them into the specific date.

This is my JSON:

[ 
   { 
      "id":"3",
      "time":"20:00",
      "hometeam":"AC Milan",
      "awayteam":"Juventus",
      "prediction":"Under 2.5",
      "odds":"1.75",
      "competition":"Serie A",
      "status":"lost",
      "date":"01-11-2019"
   },
   { 
      "id":"4",
      "time":"21:00",
      "hometeam":"FCSB",
      "awayteam":"Dinamo",
      "prediction":"Draw",
      "odds":"1.12",
      "competition":"Liga 1",
      "status":"",
      "date":"01-11-2019"
   },
   { 
      "id":"1",
      "time":"16:00",
      "hometeam":"Chelsea",
      "awayteam":"Arsenal",
      "prediction":"Over 2.5",
      "odds":"1.32",
      "competition":"Premier League",
      "status":"won",
      "date":"31-10-2019"
   },
   { 
      "id":"2",
      "time":"18:00",
      "hometeam":"Manchester United",
      "awayteam":"Liverpool",
      "prediction":"1x2",
      "odds":"1.45",
      "competition":"Premier League",
      "status":"won",
      "date":"31-10-2019"
   }
]
I want to order my JSON by date, and then have every match grouped by specific date and display them in HTML. So far, I'm displaying these 4 games, but I'm adding the date to every game; I would like to have the date, then the 2 games from 01-11-2019, again the date, 31-10-2019, then the rest of the 2 matches.

Here's the AJAX and HTML:

function updateList() {   
jQuery.ajax({
type: "GET",
url: url
dataType: 'json',
timeout: 5000,
crossDomain: true,
cache: false,
success: function(data) {
console.log(JSON.stringify(data));

var groupedData = _.groupBy(data, function(d){return d.date});
//console.log(groupedData);

var htmlText = data.map(function(o){
return `  
<div class="norm"><i class="icon-hourglass-time"></i>${o.date}</div>
<ul class="stage clearfix">
<li class="scene">
 <!-- <div class="trigger"></div> -->
 <div class="face" ontouchend="return true">
  <a class="calendar-hour poster tasklist-gray">
   <div class="max-constrain">
    <div class="first-20">
     <div class="cal-from"><strong>${o.time} <small>GMT</small></strong>
     </div>
    </div>
    <div class="second-45">
     <div class="teams">${o.hometeam}
      <br><small>vs</small>
      <br>${o.awayteam}</div><em><i class="fa fa-map-marker"></i>${o.competition}</em>
    </div>
    <div class="third-35 last-column">
     <div class="over-under">
      <div class="over-under-icon">
       <div class="over-under-text-over uppercase">
        <div class="over-under-number">${o.prediction}</div>
        <div class="odd-number">
        ${o.odds}
        </div>
        
       </div>
       <div class="touch-section uppercase"><span class="statusValue">${o.status}</span></div>
      </div>
     </div>
    </div>
   </div>
  </a>
  <div class="info">
   <div class="result-top-unch uppercase"><i class="fa fa-pause"></i>…</div>
  </div>
 </div>
</li>
</ul>
`;
});

jQuery('.container-fullscreen').append(htmlText);

},
error: function(data) {
console.log(JSON.stringify(data));
}
});
}

Thanks for the help!

toofast
  • 39
  • 2
  • 12

1 Answers1

2

Actually what you want to do has to be done in two steps.

First, group your objects by date, you can do this with lodash, since it's already in your code.

With an ES6 approach, you could do this by defining the following function:

function groupBy(list, keyGetter) {
    const map = new Map();
    list.forEach((item) => {
         const key = keyGetter(item);
         const collection = map.get(key);
         if (!collection) {
             map.set(key, [item]);
         } else {
             collection.push(item);
         }
    });
    return map;
}

It takes two arguments: your array and the function that'll be used to verify on which property it should group your data.

matchMap = groupBy(foo, match => match.date)

You have plenty example avalaible on SO, i checked this post

Then you just have to sort the array by dates:

let matchArray = Array.from(matchMap )

const sortedArray = matchArray.sort( (a, b) => {

    const dateArrayA = a[1][0].date.split('-');
    const dateArrayB = b[1][0].date.split('-');
    return new Date(dateArrayA[2], dateArrayA[1]-1, dateArrayA[0]) > new Date(dateArrayB[2], dateArrayB[1]-1, dateArrayB[0])
})

since the date property is not a valid date but a string, you have to reconstruct it when comparing the different entries.

Then the result will be a dictionary with the date as key and ordered by it.

EDIT Fetching data:

for(i=0;i<matchArray.length;i++)
{
    for(j=0;j<matchArray[i][1].length;j++){
    const currentMatch = matchArray[i][1][j];
    //Your display logic
  }

}

Hope it helps !

Community
  • 1
  • 1
Quinox
  • 573
  • 3
  • 14
  • Thank you! Now how can I display the matches in my HTML, ordered by date? Also, what if I have to iterate through multiple matches in the array? Now I have only 4 entries, but I'll definitely have a lot in production. – toofast Nov 04 '19 at 09:14
  • I'd do through a double `for` loop : One to fetch all date Another one, in the previous one, to fetch all match associated with the current date – Quinox Nov 04 '19 at 09:18
  • That sounds really crazy, lol, but thanks for the help! Hopefully will end up having this working. – toofast Nov 04 '19 at 09:20
  • I updated my response with the loop part. If you want to do it faster, you can modify the `groupBy` function and use an array instead of a map if it suits your needs. – Quinox Nov 04 '19 at 09:24
  • Looks like that doesn't work and I can't see the error since the page became unresponsive. – toofast Nov 04 '19 at 09:29
  • Sounds like a infinite loop. I'm gonna make a fiddle, give me a sec. – Quinox Nov 04 '19 at 09:31
  • Here it is. https://jsfiddle.net/92eu5yot/ I made a small mistake in the second for, i'll edit it ! – Quinox Nov 04 '19 at 09:36
  • Still have no idea how to display all of these in HTML :( – toofast Nov 04 '19 at 11:51
  • Ddi you check my fiddle ? `currentMatch` is an object, so i used json.stringify to display every properties but you can display whatever you want. Not quite sure what's the problem here. Do you use jquery ? a simple .text() or .html() would be enough. If not, look at this : https://developer.mozilla.org/fr/docs/Web/API/Element/innertHTML – Quinox Nov 04 '19 at 12:00
  • I mean I don't know how to display them in my HTML, please see the above attached HTML. – toofast Nov 04 '19 at 12:55
  • in your case, data is an array of objects, method `map` allows you to fetch every object of this array and return a new array with the newly defined objects (a string in your case. I'm note sure .map is the right way to do it, you can basically do the same thing on the inner `for` part of my code. Even if there are more modern ways of doing it, you shoud be able to parse all your string this way and then display your new DOM element with `append` – Quinox Nov 04 '19 at 13:47
  • I've added my code for rendering, as you can see, now each date is replicated 4 times instead of 2, and I still can't order the 2 matches by each specific date: https://codepen.io/toofast1/pen/OJJQQzm – toofast Nov 04 '19 at 17:47