Last active
August 29, 2015 14:26
-
-
Save edtoken/14bea32eba484731ded2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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