如何在二维数组中连接性地排序两个数组?

huangapple go评论73阅读模式
英文:

How do connectively sort 2 arrays in a 2 dimensional array?

问题

我有一个 JavaScript 中的 2D 数组:

['Daniela', 'Jonas', 'Simon', 'Vincent']
['0', '3', '0', '4']


其中数字代表用户猜测随机数字所需的次数。
我希望它看起来像这样:

['Jonas', 'Vincent', 'Simon', 'Daniela']
['3', '4', '0', '0']


基本上,按数字从低到高排序(除了0,因为用户没有完成他的运行),但名称根据数字相应地排序。

如何实现这个目标?

我尝试过像普通的 2D 数组一样排序,但不起作用,我尝试分开不同的数组并手动排序它们,但然后我不知道如何将它们连接起来。
英文:

I have this 2d Array in JavaScript:

['Daniela', 'Jonas', 'Simon', 'Vincent']
['0', '3', '0', '4']

in which the numbers stand for the amount of guesses the user took to guess a random number.
and i want it to look like this:

['Jonas', 'Vincent', 'Simon', 'Daniela']
['3', '4', '0', '0']

so basically, sorted by the numbers from lowest to highest (except 0 since the user didnt finish his run), but the names sorted accordingly to the numbers.

How (if) is this possible?

I tried sorting it like normally like a 2d Array and it didnt work, i tried splitting the different array and sorting them manually but then i dont know how to sort them connectively.

答案1

得分: 2

If you like to keep arrays, you could take an array of indices, sort by the values and map finally both arrays with the indices.

let names = ['Daniela', 'Jonas', 'Simon', 'Vincent'],
    values = ['0', '3', '0', '4'],
    indices = [...values.keys()].sort((a, b) =>
        (+values[a] || Number.MAX_VALUE) - (+values[b] || Number.MAX_VALUE)
    );

[names, values] = [names, values].map(a => indices.map(i => a[i]));

console.log(...names);
console.log(...values);
英文:

If you like to keep arrays, you could take an array of indices, sort by the values and map finally both arrays with the indices.

<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
let names = ['Daniela', 'Jonas', 'Simon', 'Vincent'],
values = ['0', '3', '0', '4'],
indices = [...values.keys()].sort((a, b) =>
(+values[a] || Number.MAX_VALUE) - (+values[b] || Number.MAX_VALUE)
);

[names, values] = [names, values].map(a =&gt; indices.map(i =&gt; a[i]));

console.log(...names);
console.log(...values);

<!-- end snippet -->

答案2

得分: 0

将原始数组映射为类似[[&#39;0&#39;, &#39;Daniela&#39;], ...]的对。然后按数字排序,将零视为一个特殊情况,始终排在排序的最后。然后使用reduce将这些对映射回原始的二维数组格式。

const arr = [['Daniela', 'Jonas', 'Simon', 'Vincent'],
             ['0', '3', '0', '4']]

console.log(arr[0].map((e,i)=>[arr[1][i],e])
  .sort(([a],[b])=>((a==0)-(b==0) || a-b))
  .reduce((a,[x,y])=>(a[0].push(y),a[1].push(x),a),[[],[]]))

希望这个翻译对你有帮助。如果你有其他问题,可以随时提出。

英文:

Map the original array into pairs like [[&#39;0&#39;, &#39;Daniela&#39;], ...]. Then sort by the number, treating zero as a special case that will always be last in the sort. Then use reduce to map the pairs back into the original 2D array format.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const arr = [[&#39;Daniela&#39;, &#39;Jonas&#39;, &#39;Simon&#39;, &#39;Vincent&#39;],
             [&#39;0&#39;, &#39;3&#39;, &#39;0&#39;, &#39;4&#39;]]

console.log(arr[0].map((e,i)=&gt;[arr[1][i],e])
  .sort(([a],[b])=&gt;((a==0)-(b==0) || a-b))
  .reduce((a,[x,y])=&gt;(a[0].push(y),a[1].push(x),a),[[],[]]))

<!-- end snippet -->

答案3

得分: 0

根据@Roko的建议,在这种特殊情况下,最好使用对象数组,因为它可以更轻松地创建一个排序函数。

然而,如果完全不可能的话,我们可以手动进行压缩:

const zipped = users.map(
  (user, index) => ({ name: user, guesses: Number(guesses[index]) })
);

然后,我们根据他们的猜测对它们进行排序。请注意,如果 user.guesses === 0,我使用 Infinity 作为排序值。

zipped.sort(
  (user1, user2) => (user1.guesses || Infinity) - (user2.guesses || Infinity)
);

然而,没有指定未完成测试的用户的顺序。因此,它们的顺序被认为是保留的。

试试看(我将zipped 分开成两个数组,以防你需要它们):

const users = ['Daniela', 'Jonas', 'Simon', 'Vincent'];
const guesses = ['0', '3', '0', '4'];

const zipped = users.map(
  (user, index) => ({ name: user, guesses: Number(guesses[index]) })
);

zipped.sort(
  (user1, user2) => (user1.guesses || Infinity) - (user2.guesses || Infinity)
);

console.log(zipped);

const [sortedUsers, sortedGuesses] = zipped.reduce(
  ([sortedUsers, sortedGuesses], currentUser) => [
    [...sortedUsers, currentUser.name],
    [...sortedGuesses, currentUser.guesses],
  ], [[], []]
);

console.log(sortedUsers, sortedGuesses);
英文:

As suggested by @Roko, an array of objects is preferred in this particular situation as it helps making a sorting function much easier.

However, if that is not at all possible we can zip them manually:

const zipped = users.map(
  (user, index) =&gt; ({ name: user, guesses: Number(guesses[index]) })
);

Then, we sort them based on their guesses. Note how I use Infinity as the sorting value if user.guesses === 0.

zipped.sort(
  (user1, user2) =&gt; (user1.guesses || Infinity) - (user2.guesses || Infinity)
);

However, how the order of users who did not complete the test was not specified. Hence, their order are assumed to be preserved.

Try it (I separated zipped back to two arrays, just in case you need them):
<!-- begin snippet: js hide: true console: true babel: false -->

<!-- language: lang-js -->

const users = [&#39;Daniela&#39;, &#39;Jonas&#39;, &#39;Simon&#39;, &#39;Vincent&#39;];
const guesses = [&#39;0&#39;, &#39;3&#39;, &#39;0&#39;, &#39;4&#39;];

const zipped = users.map(
  (user, index) =&gt; ({ name: user, guesses: Number(guesses[index]) })
);

zipped.sort(
  (user1, user2) =&gt; (user1.guesses || Infinity) - (user2.guesses || Infinity)
);

console.log(zipped);

const [sortedUsers, sortedGuesses] = zipped.reduce(
  ([sortedUsers, sortedGuesses], currentUser) =&gt; [
    [...sortedUsers, currentUser.name],
    [...sortedGuesses, currentUser.guesses],
  ], [[], []]
);

console.log(sortedUsers, sortedGuesses);

<!-- end snippet -->

答案4

得分: 0

这是 zip 函数的一个完美应用案例:

let zip = (...a) => a[0].map((_, i) => a.map(r => r[i]))

let names = ['Daniela', 'Jonas', 'Simon', 'Vincent']
let scores = [0, 3, 0, 4]

let temp = zip(scores, names);
temp.sort((x, y) => (x[0] || Infinity) - (y[0] || Infinity));
[scores, names] = zip(...temp);

console.log(...names)
console.log(...scores)
英文:

This is a perfect use case for the zip function:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

let zip = (...a) =&gt; a[0].map((_, i) =&gt; a.map(r =&gt; r[i]))

//

let names = [&#39;Daniela&#39;, &#39;Jonas&#39;, &#39;Simon&#39;, &#39;Vincent&#39;]
let scores = [0, 3, 0, 4]

let temp = zip(scores, names);
temp.sort((x, y) =&gt; (x[0] || Infinity) - (y[0] || Infinity));
[scores, names] = zip(...temp);

console.log(...names)
console.log(...scores)

<!-- end snippet -->

答案5

得分: 0

以下是翻译好的部分:

// 一个高效的排序方法,无需创建新的数组和对象。
// 最小运行时间。

const names = ['Daniela', 'Jonas', 'Simon', 'Vincent'];
const numbers = ['0', '3', '0', '4'];
for (let i = 1; i < names.length; i++) {
    for (let j = i - 1; j >= 0; j--) {
        if (numbers[j] > numbers[j + 1] && +numbers[j + 1] || !+numbers[j]) {
            [names[j], names[j + 1]] = [names[j + 1], names[j]];
            [numbers[j], numbers[j + 1]] = [numbers[j + 1], numbers[j]];
        } else {
            break;
        }
    }
}
console.log(...names);

注意:这是代码的翻译,不包含问题的回答。

英文:

An efficient sorting method, without creating new arrays and objects.
Minimum runtime.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const names = [&#39;Daniela&#39;, &#39;Jonas&#39;, &#39;Simon&#39;, &#39;Vincent&#39;];
const numbers = [&#39;0&#39;, &#39;3&#39;, &#39;0&#39;, &#39;4&#39;];
for (let i = 1; i &lt; names.length; i++) {
    for (let j = i - 1; j &gt;= 0; j--) {
        if (numbers[j] &gt; numbers[j + 1] &amp;&amp; +numbers[j + 1] || !+numbers[j]) {
            [names[j], names[j + 1]] = [names[j + 1], names[j]];
            [numbers[j], numbers[j + 1]] = [numbers[j + 1], numbers[j]];
        } else {
            break;
        }
    }
}
console.log(...names);

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年3月12日 19:05:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/75712688.html
  • javascript
  • multidimensional-array
  • sorting

如何在 :?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定