【问题标题】:Sorting array of objects by the ascending order of values related to another value按与另一个值相关的值的升序对对象数组进行排序
【发布时间】:2017-03-30 01:11:58
【问题描述】:

我希望按与另一个值相关的值的升序对 JSON 对象数组进行排序。听起来令人困惑,因为它是。我在数组中的每个对象中都有属性“列”和“顺序”。我需要的顺序是: 第 1 列中的最小数字,第 2 列中的最小数字,第 3 列中的最小数字,第 1 列中的第二小数字,第 2 列中的第二小数字,第 3 列中的第二小数字,然后继续。当 'order' 具有完全相同的值时,这很容易,您可以使用如下排序函数:

function sortCourses(a, b){
    if (a.order == b.order) {
        return (a.column - b.column);
    } else {
        return (a.order - b.order);
    }
}

问题是我并不总是这样设置它们。这是一个示例数组:

[
    {
        column: 2,
        order: 5
    },
    {
        column: 1,
        order: 1
    },
    {
        column: 3,
        order: 2
    },
    {
        column: 3,
        order: 1
    },
    {
        column: 1,
        order: 4
    },
    {
        column: 2,
        order: 1
    },
    {
        column: 3,
        order: 3
    },
    {
        column: 1,
        order: 3
    },
    {
        column: 2,
        order: 3
    },
    {
        column: 1,
        order: 2
    }
]

排序后,我需要这个数组看起来像:

[
    {
        column: 1,
        order: 1
    },
    {
        column: 2,
        order: 1
    },
    {
        column: 3,
        order: 1
    },
    {
        column: 1,
        order: 2
    },
    {
        column: 2,
        order: 3
    },
    {
        column: 3,
        order: 2
    },
    {
        column: 1,
        order: 3
    },
    {
        column: 2,
        order: 5
    },
    {
        column: 3,
        order: 3
    },
    {
        column: 1,
        order: 4
    }
]

关于如何实现这一点的任何想法?

【问题讨论】:

  • 一个数组有 sort 方法接受 1 个比较函数的参数,看起来与您提供的相似。但是,它看起来像是用于升序排序。您需要交换被减数和减数(在比较函数中进行减法)。
  • 我正在使用排序方法,抱歉应该提到这一点。我提供的比较函数将它们按 [1,1]、[2,1]、[3,1] 的顺序排列,但不知道将 [2,3] 放在 [1,2] 之后,因为它正在寻找将 [2,2] 放在它旁边,它不存在。如果您提出的建议可以做到这一点,您可以发布答案吗?谢谢。

标签: javascript jquery arrays sorting


【解决方案1】:

可能会快一点,但希望很容易理解。

const data = [
    { column: 2, order: 5 }, { column: 1, order: 1 }, { column: 3, order: 2 },
    { column: 3, order: 1 }, { column: 1, order: 4 }, { column: 2, order: 1 },
    { column: 3, order: 3 }, { column: 1, order: 3 }, { column: 2, order: 3 },
    { column: 1, order: 2 }
];

// Sort by order.
data.sort(function (a, b) {
  return (a.order - b.order);
});

// Group by column.
const groups = data.reduce(
  function (acc, value) {
    if (!acc[value.column]) {
      acc[value.column] = [];
    }
    acc[value.column].push(value);
    return acc;
  }, {});

// Get sorted columns.
const cols = Object.keys(groups).map(Number).sort();

// Loop over columns taking lowest value until we're out of values.
const out = [];
while (out.length < data.length) {
  cols.forEach(
    function (col) {
      if (groups[col].length) {
        out.push(groups[col].shift(0));
      }
    });
}

console.log(out);

【讨论】:

  • 我不确定 Javascript 中的数组与 C# 中的数组有何不同,但看起来使用 .shift() 修改数组需要在内部进行更多计算。除非 Javascript 中的数组就像一个特殊对象,其中索引只是键。然而,像这样的代码更短更干净,但您说 可能会快一点 - 恐怕我们可能需要一些实际的基准测试(在使用 .shift并在使用 for-loop 而不是 forEach 之前找到所有分组数组的最大长度。
  • 我刚刚想到了另一种方法,我们不需要找到最大长度以及使用.shift。看起来这比找到最大长度要好。
【解决方案2】:

一种相当冗长的方式,但我所做的只是将每个“组”(列)分组到一个对象中,将它们的订单推送到一个数组中。然后我只是将它们排序并粘贴进去。

var array = [
    {
        column: 2,
        order: 5
    },
    {
        column: 1,
        order: 1
    },
    {
        column: 3,
        order: 2
    },
    {
        column: 3,
        order: 1
    },
    {
        column: 1,
        order: 4
    },
    {
        column: 2,
        order: 1
    },
    {
        column: 3,
        order: 3
    },
    {
        column: 1,
        order: 3
    },
    {
        column: 2,
        order: 3
    },
    {
        column: 1,
        order: 2
    }
];

var new_array = {}

for (let item of array)
{
  if (item.column in new_array)
  {
    new_array[item.column].push(item.order);
  }
  else
  {
    new_array[item.column] = [item.order];
  }
}

let max = 0;
for (let key in new_array)
{
  max = (max < new_array[key].length) ? new_array[key].length : max;
  new_array[key].sort();
}

var final = [];

for (let i = 0; i < max; i++)
{
  for (let key in new_array)
  {
    if (i < new_array[key].length)
    {
      final.push({column: key, order: new_array[key][i]});
    }
  }
}


console.log(final);

【讨论】:

  • 谢谢。这有效,但创建了一个仅具有这些属性的新数组。我对答案投了赞成票,但选择了另一个答案,因为它使对象保持完好。
  • 啊没有意识到你需要它,只是克隆对象:)
猜你喜欢
  • 1970-01-01
  • 2022-01-05
  • 1970-01-01
  • 1970-01-01
  • 2019-10-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多