Javascript 对数组进行排序,使其在数组中首先具有特定项

Javascript 对数组进行排序,使其在数组中首先具有特定项,javascript,arrays,sorting,Javascript,Arrays,Sorting,我有这样一个数组: [{flag: true, other: 1}, {flag: true, other: 2}, {flag: false, other: 3}, {flag: true, other: 4}, {flag: true, other: 5}, {flag: true, other: 6}, {flag: false, other: 7}] 我想要这个: [{flag: false, other: 3}, {flag: false, other: 7}, {f

我有这样一个数组:

[{flag: true, other: 1},
 {flag: true, other: 2},
 {flag: false, other: 3},
 {flag: true, other: 4},
 {flag: true, other: 5},
 {flag: true, other: 6},
 {flag: false, other: 7}]
我想要这个:

[{flag: false, other: 3},
 {flag: false, other: 7},
 {flag: true, other: 1},
 {flag: true, other: 2},
 {flag: true, other: 4},
 {flag: true, other: 5},
 {flag: true, other: 6}]
基本上,我希望如果
数组[2].flag===false(或我选择的任何其他值),匹配的元素将被放在数组的第一位,但在前面的匹配元素之后。
不匹配的元素保持原来的顺序

外观的顺序很重要


如何在JavaScript中做到最好?

编写一个自定义排序函数,并使用该标志提高优先级:

array.sort(function(a,b) {
  if (!a['flag'] && b['flag'])
    return 1;
  if (a['flag'] && !b['flag'])
    return -1;
  return a['other'] - b['other']
});
基本上,我假设列表中设置了标志的条目优先于没有标志的条目。因此,如果a没有该标志,而b有,则返回1(选择b)。如果a返回a,b不返回a


在两者都设置了标志或都没有设置标志的情况下,cmp是正常的。

排序方法可以使用可选的sort函数作为参数,您可以使用该参数定义排序后元素的顺序

arr=arr.sort(函数(a,b){//使用自定义函数对数组进行排序,
//它被多次称为
//确定新的顺序。a和b是两个
//元素进行比较。JavaScript使用
//用于确定新订单的返回值:
//1-a应该比b来得晚
//-1-a应该比b来得早
//0-它们应保持当前顺序
返回a.flag==true&&b.flag==false
?1//如果a为真,b为假,则a应随后出现
:a.flag==false&&b.flag==true
?-1//如果a为假,b为真,则a应提前到来
:a.其他>b.其他
?1//如果a.other>b.other,a必须稍后再来
:a.其他
这实际上不是排序。您可以在阵列中循环两次,然后构建一个新阵列:

var result = [];
for (var i = 0; i < arr.length; i++) {
  if (arr[i].flag === false) {
    result.push(arr[i]);
  }
}
for (var i = 0; i < arr.length; i++) {
  if (!arr[i].flag === false) {
    result.push(arr[i]);
  }
}
var结果=[];
对于(变量i=0;i
您还可以使用两个结果数组和一个循环,并连接结果:

var result1 = [], result2 = [];
for (var i = 0; i < arr.length; i++) {
  if (arr[i].flag === false) {
    result1.push(arr[i]);
  } else {
    result2.push(arr[i]);
  }
}
var result = result1.concat(result2);
var result1=[],result2=[];
对于(变量i=0;i
由于要选择某些数组项,但要保持它们的原始顺序,因此需要使用
filter()
方法。此函数是一个,因此您可能需要使用该页面提供的垫片,具体取决于您支持的浏览器

(当我第一次阅读您的问题时,我认为您希望根据标志进行排序,然后根据值进行排序;为此,您可以使用内置的
sort()
方法。)


我觉得这有点简单。 因为javascript将true视为1,将false视为0,所以可以使用它们来创建这样的比较器

var comp = function(a,b){
    return a.flag*1 - b.flag*1;
}
然后你可以用这个比较器对数组进行排序

var arr = [{flag: true, other: 1},
         {flag: true, other: 2},
         {flag: false, other: 3},
         {flag: true, other: 4},
         {flag: true, other: 5},
         {flag: true, other: 6},
         {flag: false, other: 7}];
arr.sort(comp);
ECMAScript 6引入的方法(例如,
[…对象]
)使用数组的
reduce
方法使这一点相对简单:

const arr = [
  { flag: true, other: 1 },
  { flag: true, other: 2 },
  { flag: false, other: 3 },
  { flag: true, other: 4 },
  { flag: true, other: 5 },
  { flag: true, other: 6 },
  { flag: false, other: 7 }
];

const sortedArr = arr.reduce((acc, element) => {
  if (!element.flag) {
    return [element, ...acc];
  }
  return [...acc, element];
}, []);

我发现这非常有用。

一种更简单、更优雅的方法是通过两次过滤旧数组来构建一个新数组:一次按
标记:true
过滤,一次按
标记:false
过滤。总的来说,它看起来像:

// THE INITIAL ARRAY:
const originalArray = [
    {flag: true, other: 1},
    {flag: true, other: 2},
    {flag: false, other: 3},
    {flag: true, other: 4},
    {flag: true, other: 5},
    {flag: true, other: 6},
    {flag: false, other: 7}
];

// THE SORTED ARRAY:
const sortedArray = [
    ...originalArray.filter(({flag}) => flag),
    ...originalArray.filter(({flag}) => !flag)
];
在我看来,它比使用比较器或减缩器函数更容易让人阅读,而且(基于测量),它也是一个性能相当好的解决方案


性能比较: 我看到使用
arr.reduce()
比这个解决方案执行速度慢20倍左右。我用它来做比较,你也可以自己测试一下

测量
数组.reduce()
方式: 测量
array.filter()
方式:
一种解决方案是根据
标志
对数组排序,然后根据
其他

var a=[{flag:true,other:1},
{flag:true,other:2},
{flag:false,other:3},
{flag:true,other:4},
{flag:true,other:5},
{flag:true,other:6},
{flag:false,other:7}];

a、 排序((a,b)=>a.flag-b.flag)。排序((a,b)=>a.other-b.other)您可以使用值的增量进行排序

  • 标志排序
    。如果
    true
    0
    ,如果
    false,布尔值将转换为
    1
  • 其他
    排序
  • var数组=[{flag:true,other:1},{flag:true,other:2},{flag:false,other:3},{flag:true,other:4},{flag:true,other:5},{flag:true,other:6},{flag:false,other:7}];
    array.sort((a,b)=>
    a、 旗帜-b旗||
    a、 其他的
    );
    console.log(数组)
    
    。作为控制台包装{max height:100%!important;top:0;}
    对于
    false
    标记的元素,相对于彼此的顺序如何?@amn:它们是“前缀”的顺序数组的顺序应该是它们在原始数组中遇到的顺序。@amn:问题表明,与条件不匹配的元素的顺序与原始的顺序相同,我假设它也适用于与条件匹配的元素。@Guffa是,这个问题已经被编辑以解决我的合理顾虑:-),但同时也添加了许多好的答案,所以我退出…reduce方法是否缺少第二个参数(initialValue)?,在本例中是一个空数组。这不应该吗<代码>arr.reduce
    
    const arr = [
      { flag: true, other: 1 },
      { flag: true, other: 2 },
      { flag: false, other: 3 },
      { flag: true, other: 4 },
      { flag: true, other: 5 },
      { flag: true, other: 6 },
      { flag: false, other: 7 }
    ];
    
    const sortedArr = arr.reduce((acc, element) => {
      if (!element.flag) {
        return [element, ...acc];
      }
      return [...acc, element];
    }, []);
    
    // THE INITIAL ARRAY:
    const originalArray = [
        {flag: true, other: 1},
        {flag: true, other: 2},
        {flag: false, other: 3},
        {flag: true, other: 4},
        {flag: true, other: 5},
        {flag: true, other: 6},
        {flag: false, other: 7}
    ];
    
    // THE SORTED ARRAY:
    const sortedArray = [
        ...originalArray.filter(({flag}) => flag),
        ...originalArray.filter(({flag}) => !flag)
    ];
    
    const arr = [
      { flag: true, other: 1 },
      { flag: true, other: 2 },
      { flag: false, other: 3 },
      { flag: true, other: 4 },
      { flag: true, other: 5 },
      { flag: true, other: 6 },
      { flag: false, other: 7 }
    ];
    
    // Lets multiple the array items 11 times to increase the looping process:
    new Array(11).fill().forEach(x => arr.push(...arr));
    
    console.time();
    
    const reducedArr = arr.reduce((acc, element) => {
      if (element.flag === false) {
        return [element, ...acc];
      }
      return [...acc, element];
    }, []);
    
    console.timeEnd(); // RESULTS: between 285-350ms
    
    const arr = [
      { flag: true, other: 1 },
      { flag: true, other: 2 },
      { flag: false, other: 3 },
      { flag: true, other: 4 },
      { flag: true, other: 5 },
      { flag: true, other: 6 },
      { flag: false, other: 7 }
    ];
    
    // Lets multiple the array items 11 times to increase the looping process:
    new Array(11).fill().forEach(x => arr.push(...arr));
    
    console.time();
    
    const rebuiltArray = [
      ...arr.filter(x => !!x.flag),
      ...arr.filter(x => !x.flag)
    ];
    
    console.timeEnd(); // RESULTS: between 6-20ms