合并和重新排序2个数组

时间:2017-08-03 08:37:40

标签: javascript arrays charts

我正在创建一个JS图表库,当我更改数据时,我正在努力使用饼图/圆环图。我的视觉效果是使用SVG元素创建的,创建新图表很好。我正在努力改变现有图表上的数据。绘制图表后,我不希望图表在添加或删除扇区时“打开”。

例如,如果我的原始数据(比如arrOld)是

arrOld = [
    {name: "bacon", amount: 50},
    {name: "eggs", amount: 25},
    {name: "sausages", amount: 15},
    {name: "toast", amount: 10}
];

我希望将图表设置为新的数据数组(例如,arrNew),这是

arrNew = [
    {name: "bacon", amount: 50},
    {name: "hash browns", amount: 8},
    {name: "eggs", amount: 25},
    {name: "toast", amount: 10},
    {name: "sausages", amount: 15}
];

我希望新成员"hash browns""bacon""eggs"之间从0°“增长”,迫使他们分开。那部分我已经成功实现了。因为"toast""sausages"已交换位置,我希望其中一个动画(压扁)下降到0°(然后被移除),同时新的替换扇区在其新位置“增长”。所以我将有效地拥有一个中间数组(例如,arrTemp),它看起来像:

arrTemp = [
    {name: "bacon", amount: 50},
    {name: "hash browns", amount: 8, new: true},
    {name: "eggs", amount: 25},
    {name: "sausages", amount: 15, removeMe:true}
    {name: "toast", amount: 10},
    {name: "sausages", amount: 15, new:true}
];

我实际处理的数据比这个例子更复杂,但这显示了基本的想法。我可以在动画完成后删除临时数组,动画需要removeMenew属性,但动画结束后不需要保留。

临时数组必须包含与原始数组相同顺序的成员(即使它们可能将"removeMe"属性设置为true),因为这是它的起点。过渡动画。

我为...循环写了5或6,我真的很接近它的工作,但我的代码很糟糕,我确信有更好的方法。我真正做的就是合并2个数组:o(

感谢任何帮助:o)

这是我目前的代码:

var o;

//get the wedges from the previous animation call (the "old" array)
anWedges=gs.wedges[this._drawCall-1].clone();

//now find the new members:
//first set our new array to the current data:
var wedgesNew=gs.wedges[this._drawCall].clone();
//set "precedes" and "follows" properties:
for (w=0; w<wedgesNew.length; w++){
    wedgesNew[w].precedes=null;
    wedgesNew[w].follows=null;
    if (w>0){
        wedgesNew[w].follows=wedgesNew[w-1].id;
    }
    if(w<wedgesNew.length-1){
        wedgesNew[w].precedes=wedgesNew[w+1].id;
    }
}

//remove any members from our new array that were in the old one:
for (o=0; o<anWedges.length; o++){
    anWedges[o].new=false;
    anWedges[o].moved=false;
    for (w=0; w<wedgesNew.length; w++){
        if (anWedges[o].id===wedgesNew[w].id){
            wedgesNew.splice(w,1);
            break;
        }
    }
}

//add our new array members to the old array:
for (w=0; w<wedgesNew.length; w++){
    wedgesNew[w].new=true;
    //if its "follow" member doesn't exist, put it at the front:
    if (wedgesNew[w].follows===null){
        anWedges.unshift(wedgesNew[w]);
    }
    else{
        //otherwise, put it where it should be:
        for (o=0; o<anWedges.length; o++){
            if (anWedges[o].id===wedgesNew[w].follows){
                anWedges.splice(o+1, 0, wedgesNew[w]);
                break;
            }
        }
    }
}

//add a "follows" property to any members that don't have one:
for (o=0; o<anWedges.length; o++){
    if (isNil(anWedges[o].follows) && o > 0){
        for (w =0; w<gs.wedges[this._drawCall].length-1; w++){
            if (gs.wedges[this._drawCall][w+1].id === anWedges[o].id){
                anWedges[o].follows=gs.wedges[this._drawCall][w].id;
            }
        }
    }
}

//see if we need to move any members:
var prevID="";
for (o=0; o<anWedges.length; o++){
    var wRequired=false;
    for (w=0; w<gs.wedges[this._drawCall].length;w++){
        if (gs.wedges[this._drawCall][w].id===anWedges[o].id){
            wRequired=true;
            break;
        }
    }
    if (!wRequired){
        anWedges[o].removeMe=true;
    }
    else{
        if (o>0 && !anWedges[o].new){
            if(prevID!=="" && anWedges[o].follows!==prevID && !anWedges[o].removeMe){
                var wMoved=cloneObj(anWedges[o]);
                wMoved.moved=true;
                anWedges[o].removeMe=true;
                anWedges[o].id=anWedges[o].id+"_old";
                for (w=0;w<anWedges.length;w++){
                    if (anWedges[w].id===anWedges[o].follows){
                        anWedges.splice(w+1,0, wMoved);
                        break;
                    }
                }
            }
        }
        prevID=anWedges[o].id;
    }
}

1 个答案:

答案 0 :(得分:0)

好的,我已经对它进行了分类。

我使用了来自David Furlongthis question唯一函数的变体来合并两个数组:

//returns a NEW array with duplicate members removed
Array.prototype.unique = function(prop) {
    var a = this.concat();
    for(var i=0; i<a.length; ++i) {
        for(var j=i+1; j<a.length; ++j) {
            if (!isNil(prop)){
                if (a[i].hasOwnProperty(prop) && a[j].hasOwnProperty(prop)) {
                    if(a[i][prop] === a[j][prop]){
                        a.splice(j--, 1);
                    }
                }
            }
            else{
                if(eve.isEqual(a[i], a[j])){
                    a.splice(j--, 1);
                }
            }
        }
    }
    return a;
};

和此函数按对象首选索引对对象数组进行排序:

//sort an array of objects by an object property
function sortByProperty(prop) {
    return function (a,b) {
        if (a.hasOwnProperty(prop) && b.hasOwnProperty(prop)) {
            return (a[prop] < b[prop]) ? -1 : (a[prop] > b[prop]) ? 1 : 0;
        }
    };
}

我的代码现在更加简洁:

var oldWedges=gs.wedges[this._drawCall-1].clone();
var newWedges=gs.wedges[this._drawCall].clone();

//merge the old and new arrays, omitting duplicate IDs (start with the new array, that way we honour the new order):
var anWedges = newWedges.concat(oldWedges).unique("id");
//tag any new members as new:
for (n=0; n<anWedges.length;n++){
    if (oldWedges.indexOfProp("id", anWedges[n].id) === -1){
        anWedges[n].new=true;
    }
}

//check that the order of the old members hasn't changed
//if it has, tag them for moving:
for (o=0; o<oldWedges.length;o++){
    n = anWedges.indexOfProp("id", oldWedges[o].id);
    var t=0;
    var tmp = null;
    var prev=null;
    var next=null;
    if (o>0){
        t=o-1;
        tmp=oldWedges[t];
        while (t>0 && anWedges.indexOfProp("id", tmp.id) === -1){
            tmp=oldWedges[t];
            t-=1;
        }
        prev=tmp;
    }
    if (o<oldWedges.length-1){
        t=o+1;
        tmp=oldWedges[t];
        while (t<oldWedges.length-1 && anWedges.indexOfProp("id", tmp.id) === -1){
            tmp=oldWedges[t];
            t+=1;
        }
        next=tmp;
    }
    if (!isNil(prev)){
        if (prev.i>=anWedges[n].i){
            anWedges[n].moveMe=true;
        }
    }
    if (!isNil(next)){
        if (next.i<=anWedges[n].i){
            anWedges[n].moveMe=true;
        }
    }
}

//create duplicate wedges for any that need to move so that we can animate them collapsing:
for (n=0;n<anWedges.length;n++){
    if (anWedges[n].moveMe){
        anWedges[n].moveMe=false;
        var oldWedge=cloneObj(oldWedges[oldWedges.indexOfProp("id", anWedges[n].id)]);
        oldWedge.sector=oldWedge.sector.clone();
        var oldIndex=0;
        if (oldWedges.indexOfProp("id", oldWedge.id)>0){
            var prevID=oldWedges[oldWedges.indexOfProp("id", oldWedge.id)-1].id;
            oldIndex=anWedges.indexOfProp("id", prevID)+1;
        }
        oldWedge.id+="_old";
        oldWedge.removeMe=true;
        anWedges[n].moved=true;
        anWedges.splice(oldIndex, 0, cloneObj(oldWedge));
    }
}

//tag any old wedges that are obsolete for removal
for (n=0;n<anWedges.length;n++){
    if (newWedges.indexOfProp("id", anWedges[n].id)===-1){
        anWedges[n].removeMe=true;
    }
}

//sort wedges by their preferred order:
anWedges.sort(sortByProperty("i"));

它仍然不像我想的那样整洁,但它适用于我的所有测试用例。 :O)