JavaScript:通过交替使用每种类型的对象来排序数组

时间:2017-09-27 09:45:24

标签: javascript arrays sorting

我有一个像这样的对象数组(按类型排序,相同类型的对象是相同的):

[
    { "type":"A", "height":50, "width":80 },
    { "type":"A", "height":50, "width":80 },
    { "type":"B", "height":20, "width":100 },
    { "type":"B", "height":20, "width":100 },
    { "type":"C", "height":90, "width":10 }
]

我希望将所有这些对象放在一个数组中,该数组通过交替使用每种类型的对象来排序:

[
    { "type":"A", "height":50, "width":80 },
    { "type":"B", "height":20, "width":100 },
    { "type":"C", "height":90, "width":10 },
    { "type":"A", "height":50, "width":80 },
    { "type":"B", "height":20, "width":100 }
]

5 个答案:

答案 0 :(得分:2)

您可以采用Map并进行迭代,直到按正确的顺序处理所有项目。



var array = [{ type: "A", height: 50, width: 80 }, { type: "A", height: 50, width: 80 }, { type: "B", height: 20, width: 100 }, { type: "B", height: 20, width: 100 }, { type: "C", height: 90, width: 10 }],
    order = ['A', 'B', 'C'],
    types = new Map(order.map(k => [k, []])),
    result = [];

array.forEach(o => types.get(o.type).push(o));

while (types.size) {
    types.forEach((a, k) => (result.push(a.shift()), a.length || types.delete(k)));
}

console.log(result);

.as-console-wrapper { max-height: 100% !important; top: 0; }




答案 1 :(得分:0)

这是我的尝试。它不是最有效的,但只要输入不是太大就应该很好。

它假定类型将始终是一个字符串,但它不假设它们将始终是A,B和C.它循环输入数据以确定类型并将匹配类型一起收集为“分区”。一旦完成它就会循环遍历每个分区的类型转移条目,直到它完成为止。如果分区具有不同数量的条目,则没有问题,但是会浪费时间来移动不存在的对象。

您提到每种类型的对象都是相同的,但我没有考虑到这些细节。如果“相同”是指“同一个对象”(即obj1 === obj2),那么您可以利用它来跟踪计数而不是创建所有这些分区数组。

var input = [
    { "type":"A", "height":50, "width":80 },
    { "type":"A", "height":50, "width":80 },
    { "type":"B", "height":20, "width":100 },
    { "type":"B", "height":20, "width":100 },
    { "type":"C", "height":90, "width":10 }
];

var types = [];
var partitions = {};

input.forEach(function(row) {
    var type = row.type;
    
    if (partitions[type]) {
        partitions[type].push(row);
    }
    else {
        partitions[type] = [row];
        types.push(type);
    }
});

var output = [];

while (output.length < input.length) {
    types.forEach(function(type) {
        var next = partitions[type].shift();
        
        if (next) {
            output.push(next);
        }
    });
}

console.log(output);

答案 2 :(得分:0)

在ES6中写了一小段。

应该相当容易
const getAlternate = (ar) => {
    const types = [];
    const objects = {};
    const typeCounts = {};
    let totalCount = 0;

    ar.forEach((object) => { 
        if(!types.includes(object.type)) {
            types.push(object.type);
            objects[object.type] = object;
            typeCounts[object.type] = 1;
        } else {
            typeCounts[object.type]++;
        }
        totalCount++;
    });

    /**
     * at this point, the state variables will look like this:
     * types ['A', 'B', 'C']
     * objects { A: { type: 'A', height: 50, width: 80 },
     *           B: { type: 'B', height: 20, width: 100 },
     *           C: { type: 'C', height: 90, width: 10 } }
     * typeCounts { A: 2, B: 2, C: 1 }
     * totalCount 5
     *
     * now we can use this data to get the alternation!
     */

    const newAr = [];
    let typeIndex = 0;
    while(totalCount > 0) {
        totalCount--;

        let type = types[typeIndex];
        newAr.push(objects[type]);
        typeCounts[type]--;

        if(typeCounts[type] <= 0) {
            types.splice(typeIndex, 1);
            typeIndex--;
            delete objects[type];
            delete typeCounts[type];
        }

        typeIndex = (typeIndex + 1) % types.length;
    }

    return newAr
}

我做的第一件事是设置一些状态,以便以后更容易迭代这些类型,包括每种类型的列表,每种类型的对象的副本,以及每种类型的计数

从那里,我宣布一个新的数组,只需使用模数跟随交替,删除我不再需要的所有内容

// here we invoke the function
console.log(getAlternate([
    { "type":"A", "height":50, "width":80 },
    { "type":"A", "height":50, "width":80 },
    { "type":"B", "height":20, "width":100 },
    { "type":"B", "height":20, "width":100 },
    { "type":"C", "height":90, "width":10 }
]));

// and, as expected, we get
[
    {"type":"A","height":50,"width":80},
    {"type":"B","height":20,"width":100},
    {"type":"C","height":90,"width":10},
    {"type":"A","height":50,"width":80},
    {"type":"B","height":20,"width":100}
]

答案 3 :(得分:0)

试试这个(评论中的解释)

var inputArr = [
    { "type":"A", "height":50, "width":80 },
    { "type":"A", "height":50, "width":80 },
    { "type":"B", "height":20, "width":100 },
    { "type":"B", "height":20, "width":100 },
    { "type":"C", "height":90, "width":10 }
];

//create an index by type
var typeMap = {};

inputArr.forEach( function( item ){
  typeMap[ item.type ] = typeMap[ item.type ] || [];
  typeMap[ item.type ].push( item );
});

//get sorted type-list
var sortedKeyList = Object.keys( typeMap ); //assuming that keys are always going to be uppercase strings

var output = [];

var noMoreItems = false;

//iterate till there is nothing to iterate
while( !noMoreItems )
{
   //add the top item of every key of the map
   sortedKeyList.forEach( function( key ){      
      var arr = typeMap[ key ];
      output = output.concat(arr.splice(0,1));
      typeMap[ key ] = arr;
   });
   //remove the empty array keys in the map
   sortedKeyList = sortedKeyList.filter( function( key ){
      return typeMap[ key ].length > 0;
   });

   noMoreItems = ( output.length == inputArr.length );  
}

console.log( output );

答案 4 :(得分:0)

因此,既然你有订购的物品,那么你也可以这样做;

function braide(a){
  // get the chunks ie [a,a,a,a,a,b,b,b,c,c,d] -> [[a,a,a,a,a],[b,b,b],[c,c],[d]]
  var chunks = a.reduce((r,o,i,a) => a[i+1] && o.type !== a[i+1].type ? (r[r.length-1].push(o),r.push([]),r)
                                                                      : (r[r.length-1].push(o),r),[[]]);
  // find the longest chunk by appending items from every chunk at the same index position
  return chunks.reduce((p,c) => p.length > c.length ? p : c)
               .reduce((r,_,i) => (chunks.forEach(c => c[i] && r.push(c[i])),r), []);
}

var data = [{"type":"A","height":50,"width":80},{"type":"A","height":50,"width":80},{"type":"A","height":50,"width":80},{"type":"A","height":50,"width":80},{"type":"A","height":50,"width":80},{"type":"B","height":20,"width":100},{"type":"B","height":20,"width":100},{"type":"B","height":20,"width":100},{"type":"C","height":90,"width":10},{"type":"C","height":90,"width":10},{"type":"D","height":30,"width":70}];

console.log(braide(data));