0

I am generating an array of calendar events and then (using code I got from user 'Cooper') I am deduplicating the list to create a new array: dedList

// This code creates a deduplicated array (dedList) from my array 'events' (parts of this code are from Cooper on StackOverflow... and I don't really understand it all)
var dedList=[];
var obj={eA:[]};
for(var i=0;i<events.length;i++) {
  var key=events[i].getTitle() + events[i].getDescription();
  if(!obj.hasOwnProperty(key)) {
    obj[key]={
      title: events[i].getTitle(),
      description: events[i].getDescription(),
      guest_list: events[i].getGuestList(),
      guests: events[i].getGuestList().length,
      start: events[i].getStartTime(),
      end: events[i].getEndTime(),
      recurs: events[i].isRecurringEvent(),
      duration: "",
      creator: events[i].getCreators(),
      color: events[i].getColor() ,
      copies: 0,
      category: "",
    };
    obj.eA.push(key);
  }else{
    obj[key].copies+=1; //count the copies
  }  
}
for(var i=0;i<obj.eA.length;i++) {
  dedList.push(obj[obj.eA[i]]);
}

This is working perfectly, but I'm using some well shared code to sort dedList by "category" and it's generating error I've never seen before: "Comparison method violates its general contract." Here's the line causing the error, followed by the function I am using:

dedList.sort(dynamicSort("category")); // this line generates the error

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1);
    }
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

Any suggestions? I'm pretty new to google scripting so I don't completely understand how the dynamicSort function works, and that is making it hard for me to debug the error. Thanks!


MCVE:

function sortTest() {
  var arr = [];
  for (i = 0; i < 50; ++i) {
    arr.push({ a: '' }, {}, { a: {} });
  }
  Logger.log(arr.sort(dynamicSort('a')));
}
function dynamicSort(property) {
    var sortOrder = 1;
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}
  • Engine: Rhino (Old)
  • Error:

Comparison method violates its general contract

Community
  • 1
  • 1
  • *The array looks like this:*. Show it with quotes `" hello"` and brackets: `["hello","world"]` – TheMaster Feb 15 '20 at 11:57
  • Okay, I updated the way I'm displaying the array. Thanks for the feedback! – John Cutter Feb 15 '20 at 12:53
  • Your array and object are not valid. `category` cannot be left `:` like that. It should be assigned(to a empty string perhaps?) or left out completely. Read [mcve]. We should be able to reproduce the entire error. – TheMaster Feb 15 '20 at 13:44
  • 1
    Does this answer your question? ["Comparison method violates its general contract!"](https://stackoverflow.com/questions/8327514/comparison-method-violates-its-general-contract) – TheMaster Feb 15 '20 at 13:44
  • Thanks for your help. I tried to grab some code that approximates what my array looks like, but that clearly wasn't helpful so I just removed it. The only reason I was trying to show what my array looks like is because one of the values is an array, and I'm wondering if that is the root of my problem. Thanks again for your help! – John Cutter Feb 15 '20 at 13:53
  • 1
    You should probably provide us with *exactly* how your `Array` looks like, preferably a complete sample. The sorting function mentioned is the usual "-1,0,1" function and looks deterministic to me. Btw, what context are you using the function in (checked in V8 and Rhino for GAS - no errors)? Maybe your objects redefine `toString()` behaviour? Re: `Array` as value - should not matter – Oleg Valter is with Ukraine Feb 15 '20 at 14:03
  • 1
    Thank you, Oleg. I just added my array code, minus the three lines that generate the calendar 'events' array. – John Cutter Feb 15 '20 at 14:25
  • @JohnCutter, thanks, much better! Now we can take a closer look. One more question to go - do you indeed sort by `category`? – Oleg Valter is with Ukraine Feb 15 '20 at 14:37
  • And, to follow up on my previous comment, is the `category` property always an empty `String`? Sure does look like that from the code. Either this is not an exact replication of the context, or I am out of ideas, because it works perfectly fine when I imlement it (both V8 and Rhino). Could you please provide full code, including the context (is this all global or encapsulated in a function?) of the deduplicator function, when the `dynamicSort` is declared and when it is called, etc – Oleg Valter is with Ukraine Feb 15 '20 at 14:50
  • I posted my code on github. (I hope that's allowed here.) Here's the link: https://github.com/TurkMcGill/calendar_tool/blob/master/Calendar_Code – John Cutter Feb 15 '20 at 15:34
  • Also, I'm not sure what you mean when you say, "Do you indeed sort by category". Category always starts as an empty string, then I apply user-created rules to give calendar events category names, like: "Management Meeting". Depending on the rules, many events are left with no category text, and I'd like to sort my list so these appear first. (Thanks again for the help!) – John Cutter Feb 15 '20 at 15:42
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/207890/discussion-between-oleg-valter-and-john-cutter). – Oleg Valter is with Ukraine Feb 15 '20 at 16:01

2 Answers2

1

Thanks for all the help. The code I posted works fine; the problem was that I had another function that was changing some category values to "undefined". I fixed this and my problem went away, and my array is sorting perfectly now.

I was going to delete this post, but the MCVE added by @TheMaster may still be relevant? I'll leave it for now.

0

Have you tried dedList.sort(function(a,b){return a.category-b.category});

or vice-versa dedList.sort(function(a,b){return b.category-a.category});

also you should remove the trailing comma from this line category: "",

If that doesn't work I'd consider making life easier by initializing all of the categories with "AAAAA";

Cooper
  • 59,616
  • 6
  • 23
  • 54