【问题标题】:Order array by predefined rules按预定义规则排序数组
【发布时间】:2016-10-06 21:40:52
【问题描述】:

我有一系列货币["GBP", "EUR", "NOK", "DKK", "SKE", "USD", "SEK", "BGN"]。如果货币存在于数组的开头,我想通过移动预定义列表来订购它。预定义列表为['EUR', 'USD', 'DKK', 'SKE', 'NOK', 'GBP']。 所以在这种情况下它应该返回['EUR', 'USD', 'DKK', 'SKE', 'NOK', 'GBP', 'SEK', BGN']

但如果未过滤的数组不包含预定义列表中的所有值,它也应该正确排序。例如:["GBP", "EUR", "NOK", "LTU", "ZGN"] 应该看起来像 ['EUR', 'NOK', 'GBP', 'LTU', 'ZGN'

我试图使用这个函数对其进行排序:

list.sort(c => ['EUR', 'USD', 'DKK', 'SKE', 'NOK', 'GBP'].indexOf(c))

但它将所有预定义的货币放在列表的末尾,而不是在 from。也许有更好的方法来做到这一点?

【问题讨论】:

  • .sort() 的回调接受参数 - 第一个和第二个比较器。您可以使用 list.sort(( c, d ) => [...].indexOf(c) > [...].indexOf(d) ? 1 : [...].indexOf(c) < [...].indexOf(d) ? -1 : 0); 做同样的事情,但是,根据需要调整 >< 标志。

标签: javascript arrays sorting ecmascript-6


【解决方案1】:

这是我的解决方案。 :-)

//custom index of
Array.prototype.customIndexOf = function(a){
  return this.indexOf(a) === -1 ? Infinity : this.indexOf(a);
}

let orderArr = ['EUR', 'USD', 'DKK', 'SKE', 'NOK', 'GBP'];


/*test case 1*/
let urList = ["GBP", "EUR", "NOK", "DKK", "SKE", "USD", "SEK", "BGN"];
urList.sort((a, b) => { return orderArr.customIndexOf(a) - orderArr.customIndexOf(b); });
console.log(urList); //[ 'EUR', 'USD', 'DKK', 'SKE', 'NOK', 'GBP', 'SEK', 'BGN' ]

/*test case 2*/
let newList = ["GBP", "EUR", "NOK", "LTU", "ZGN"];

newList.sort((a, b) => { return orderArr.customIndexOf(a) - orderArr.customIndexOf(b); });
console.log(newList); //[ 'EUR', 'NOK', 'GBP', 'LTU', 'ZGN' ]

希望这是你需要的:-)

【讨论】:

  • 为什么是Number.MAX_VALUE?只需使用Infinity
  • 任何东西.. 我们需要一个大值.. 进行比较.. :)
  • 但是有多大? 10000够吗? 2^31 够吗?更好地使用可用的最大价值 - Infinity。诚然,由于indexOf 不能返回任何大于数组索引的值,所以任何大于 2^32 的值都可以,而Number.MAX_VALUE 远高于此值,所以没关系。
【解决方案2】:

我猜这个也可以这样实现

Array.prototype.intersect = function(a) {
  return this.filter(e => a.includes(e));
};
Array.prototype.excludes = function(a) {
  return this.filter(e => !a.includes(e));
};
var getCur = (p,c) => p.intersect(c).concat(c.excludes(p)),
      cur1 = ["GBP", "EUR", "NOK", "DKK", "SKE", "USD", "SEK", "BGN"],
      cur2 = ["GBP", "EUR", "NOK", "LTU", "ZGN"],
       pdl = ['EUR', 'USD', 'DKK', 'SKE', 'NOK', 'GBP', 'SEK', 'BGN'];
console.log(getCur(pdl,cur1));
console.log(getCur(pdl,cur2));

【讨论】:

  • 既然你在使用 ES6,最好选择a.includes(e)
【解决方案3】:

您可以使用sorting with map 和哈希表进行排序。如果该值不在哈希表中,则采用原始顺序。

var order = ['EUR', 'USD', 'DKK', 'SKE', 'NOK', 'GBP'],
    orderObj = Object.create(null),
    data = ["GBP", "EUR", "NOK", "DKK", "SKE", "USD", "SEK", "BGN"];

// generate hash table
order.forEach((a, i) => orderObj[a] = i + 1);

// temporary array holds objects with position and sort-value
var mapped = data.map((el, i) => { return { index: i, value: orderObj[el] || Infinity }; });

// sorting the mapped array containing the reduced values
mapped.sort((a, b) => a.value - b.value || a.index - b.index);

// assigning the resulting order
var data = mapped.map(el => data[el.index]);

console.log(data);

【讨论】:

  • 好答案。但是由于我使用的是 ES6,所以最后的代码部分可以写在一行中data .map((el, i) => { return { index: i, value: order[el] || 1000 }; }) .sort((a, b) => a.value - b.value || a.index - b.index) .map(el => d[el.index]);
  • 而不是1000,最好使用正确的值Infinity :-)
  • @Bergi,好主意 :-)
【解决方案4】:

var tabCurrency = ['GBP', 'EUR', 'NOK', 'DKK', 'SKE', 'USD', 'SEK', 'BGN'];

var tabPredef = ['EUR', 'USD', 'DKK', 'SKE', 'NOK', 'GBP'];

var newTabGood = [];

    tabPredef.forEach(function (itemPredef, indexPref) {

         var indexTemp;

         tabCurrency.forEach(function (itemCurrency, indexCurrency) {
               if(itemPredef == itemCurrency)
               {
                  newTabGood.push(itemPredef);
                  indexTemp = indexCurrency;
               }
         })

         tabCurrency.splice(indexTemp, 1)
   }) 


 var resultat = newTabGood.concat(tabCurrency);

 console.log(resultat)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-31
    • 2012-09-11
    • 2016-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多