Skip to content

Instantly share code, notes, and snippets.

@edtoken
Last active August 29, 2015 14:26
Show Gist options
  • Save edtoken/14bea32eba484731ded2 to your computer and use it in GitHub Desktop.
Save edtoken/14bea32eba484731ded2 to your computer and use it in GitHub Desktop.
var itemIdFieldName = 'id'; // поле в котором хранится id одного элемента
var numberGroupPrefix = '_'; // разделитель для числовых групп
var maxNumberGroupItemsLength = 3; // максимальное количество уникальных элементов в числовой группе
// создает числовую группу по значениям
var createGroupByValue = function(start, end, index, type){
if(!index[start + numberGroupPrefix + end]){
index[start + numberGroupPrefix + end] = {
items:[],
start:start,
end:end,
type:type,
sorted:false
}
}
return index[start + numberGroupPrefix + end];
};
// ->>>> вот ниже магия
// создает группы для группировки числовых значений
var createIndexNumberGroups = function(value, indexObj, type){
var start;
var end;
if(_.isEmpty(indexObj.index)){
start = 0;
end = value;
return createGroupByValue(start, end, indexObj.index, type);
}
// получаю все существующие числовые группы
// пытаюсь найти подходящую группу
for(var g1 in indexObj.index){
if(value >= indexObj.index[g1].start
&& value <= indexObj.index[g1].end
&& indexObj.index[g1].items.length < maxNumberGroupItemsLength){
indexObj.index[g1].sorted = false;
return indexObj.index[g1];
}
}
// группа не была найдена, или её размер слишком велик
// надо проверить размер всех групп
// найти подходящую (или создать)
// и вернуть
for(var g in indexObj.index){
// группа стала слишком большой, её надо разбить
if(indexObj.index[g].items.length >= maxNumberGroupItemsLength ){
// дальше по коду я могу резать группы,
// поэтому все они должны быть отсортированы
//if(!indexObj.index[g].sorted){
// //indexObj.index[g].sorted = true;
//}
// сортировка каждый раз - уменьшает скорость работы
// надо сделать более интеллектуальное добавление значений, что бы не приходилось всегда сортировать
if(!indexObj.index[g].sorted){
indexObj.index[g].items.sort(function(a, b){
if(a.value > b.value) return 1;
if(a.value < b.value) return -1;
return 0;
});
indexObj.index[g].sorted = true;
}
// теперь надо проверить не состоит ли группа из одинаковых значений
// если в ней все значения одинаковые - я не могу её разрезать
var uniq = _.uniq(indexObj.index[g].items, function(item){
return item.value;
});
// нужно резать массив только, если уникальных элементов больше maxNumberGroupItemsLength
if(uniq.length > maxNumberGroupItemsLength){
var length = Math.ceil(indexObj.index[g].items.length / 2);
var items1 = indexObj.index[g].items.slice(0, length);
var items2 = indexObj.index[g].items.slice(length);
var firstGroup = createGroupByValue(items1[0].value, items1[items1.length -1].value, indexObj.index, type);
var secondGroup = createGroupByValue(items2[0].value, items2[items2.length -1].value, indexObj.index, type);
firstGroup.items = firstGroup.items.concat(items1);
secondGroup.items = secondGroup.items.concat(items2);
delete indexObj.index[g];
}
}
}
// снова пытаюсь найти подходящую группу
// теперь уже без проверки на максимальное количество элементов
// т.к. группы были ранее разбиты и если одна из них слишком большая - значит в ней повторения (одинаковые значения)
// а их я ложу в одну группу даже, если размер превышает допустимый
for(var g2 in indexObj.index){
if(value >= indexObj.index[g2].start && value <= indexObj.index[g2].end){
indexObj.index[g2].sorted = false;
return indexObj.index[g2];
}
}
// группа для числа не была найдена
// значит надо расширить одну из существующих групп до текущего числа
// тоесть имея 2 группы 1-3 и 6-7, и добавляя число "5" нужно группу 6-7 (именно 6-7 т.к. она ближе)
// рассширить и сделать вместо 6-7 5-7 (в следующих интерациях эта группа будет наполнена и разбита в случае необходимости)
// magicData определяет какую группу надо модифицировать
var magicData = {
groupName:false,
create:{
start:false,
end:false
},
start:false,
end:false,
type:'number',
extType:false,
diff:false
};
var diff;
var extType;
for(var group in indexObj.index) {
var gStart = indexObj.index[group].start;
var gEnd = indexObj.index[group].end;
if(gStart > value){
extType = 1;
diff = gStart - value;
}
if(gEnd < value){
extType = 2;
diff = value - gEnd;
}
// если разница меньше, чем рассчитанная ранее - записываю инфу
// переделать используя continue
if(!magicData.diff || diff < magicData.diff){
magicData.diff = diff;
magicData.extType = extType;
magicData.start = gStart;
magicData.end = gEnd;
magicData.groupName = group;
}
}
switch(magicData.extType){
case 1:
magicData.create.start = value;
magicData.create.end = magicData.end;
break;
case 2:
magicData.create.start = magicData.start;
magicData.create.end = value;
break;
}
var newGroup = createGroupByValue(magicData.create.start, magicData.create.end, indexObj.index, type);
var cloneItemsOldGroup = indexObj.index[magicData.groupName].items.slice(0);
delete indexObj.index[magicData.groupName]; // удаляю группу которая не нужна
newGroup.items = newGroup.items.concat(cloneItemsOldGroup);
return newGroup;
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment