Sort Two Arrays the Same Way

Sort two arrays the same way

You can sort the existing arrays, or reorganize the data.

Method 1:
To use the existing arrays, you can combine, sort, and separate them:
(Assuming equal length arrays)

var names = ["Bob","Tom","Larry"];
var ages = ["10", "20", "30"];

//1) combine the arrays:
var list = [];
for (var j = 0; j < names.length; j++)
list.push({'name': names[j], 'age': ages[j]});

//2) sort:
list.sort(function(a, b) {
return ((a.name < b.name) ? -1 : ((a.name == b.name) ? 0 : 1));
//Sort could be modified to, for example, sort on the age
// if the name is the same. See Bonus section below
});

//3) separate them back out:
for (var k = 0; k < list.length; k++) {
names[k] = list[k].name;
ages[k] = list[k].age;
}

This has the advantage of not relying on string parsing techniques, and could be used on any number of arrays that need to be sorted together.

Method 2: Or you can reorganize the data a bit, and just sort a collection of objects:

var list = [
{name: "Bob", age: 10},
{name: "Tom", age: 20},
{name: "Larry", age: 30}
];

list.sort(function(a, b) {
return ((a.name < b.name) ? -1 : ((a.name == b.name) ? 0 : 1));
});

for (var i = 0; i<list.length; i++) {
alert(list[i].name + ", " + list[i].age);
}

For the comparisons,-1 means lower index, 0 means equal, and 1 means higher index. And it is worth noting that sort() actually changes the underlying array.

Also worth noting, method 2 is more efficient as you do not have to loop through the entire list twice in addition to the sort.

http://jsfiddle.net/ghBn7/38/

Bonus Here is a generic sort method that takes one or more property names.

function sort_by_property(list, property_name_list) {
list.sort((a, b) => {
for (var p = 0; p < property_name_list.length; p++) {
prop = property_name_list[p];
if (a[prop] < b[prop]) {
return -1;
} else if (a[prop] !== a[prop]) {
return 1;
}
}
return 0;
});
}

Usage:

var list = [
{name: "Bob", age: 10},
{name: "Tom", age: 20},
{name: "Larry", age: 30},
{name: "Larry", age: 25}
];

sort_by_property(list, ["name", "age"]);

for (var i = 0; i<list.length; i++) {
console.log(list[i].name + ", " + list[i].age);
}

Output:

  • Bob, 10
  • Larry, 25
  • Larry, 30
  • Tom, 20

How to sort two lists (which reference each other) in the exact same way

One classic approach to this problem is to use the "decorate, sort, undecorate" idiom, which is especially simple using python's built-in zip function:

>>> list1 = [3,2,4,1, 1]
>>> list2 = ['three', 'two', 'four', 'one', 'one2']
>>> list1, list2 = zip(*sorted(zip(list1, list2)))
>>> list1
(1, 1, 2, 3, 4)
>>> list2
('one', 'one2', 'two', 'three', 'four')

These of course are no longer lists, but that's easily remedied, if it matters:

>>> list1, list2 = (list(t) for t in zip(*sorted(zip(list1, list2))))
>>> list1
[1, 1, 2, 3, 4]
>>> list2
['one', 'one2', 'two', 'three', 'four']

It's worth noting that the above may sacrifice speed for terseness; the in-place version, which takes up 3 lines, is a tad faster on my machine for small lists:

>>> %timeit zip(*sorted(zip(list1, list2)))
100000 loops, best of 3: 3.3 us per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100000 loops, best of 3: 2.84 us per loop

On the other hand, for larger lists, the one-line version could be faster:

>>> %timeit zip(*sorted(zip(list1, list2)))
100 loops, best of 3: 8.09 ms per loop
>>> %timeit tups = zip(list1, list2); tups.sort(); zip(*tups)
100 loops, best of 3: 8.51 ms per loop

As Quantum7 points out, JSF's suggestion is a bit faster still, but it will probably only ever be a little bit faster, because Python uses the very same DSU idiom internally for all key-based sorts. It's just happening a little closer to the bare metal. (This shows just how well optimized the zip routines are!)

I think the zip-based approach is more flexible and is a little more readable, so I prefer it.


Note that when elements of list1 are equal, this approach will end up comparing elements of list2. If elements of list2 don't support comparison, or don't produce a boolean when compared (for example, if list2 is a list of NumPy arrays), this will fail, and if elements of list2 are very expensive to compare, it might be better to avoid comparison anyway.

In that case, you can sort indices as suggested in jfs's answer, or you can give the sort a key function that avoids comparing elements of list2:

result1, result2 = zip(*sorted(zip(list1, list2), key=lambda x: x[0]))

Also, the use of zip(*...) as a transpose fails when the input is empty. If your inputs might be empty, you will have to handle that case separately.

C - Sort two arrays the same way

The better solution is to group the data into an array of structures, then sort that based on the desired key (i.e. the a values):

struct my_data {
int a;
int b;
};

struct my_data data[100];

static int data_cmp(const void *a, const void *b)
{
const struct my_data *da = a, *db = b;

return da->a < db->a ? -1 : da->a > db->a;
}

qsort(data, sizeof data / sizeof *data, sizeof *data, data_cmp);

This uses qsort() to sort, which is typically highly desirable.

How to sort two arrays by same index?

Use Array.Sort<TKey, TValue>(TKey[] keys, TValue[] items) that accepts two input arrays, one is the array of keys, the other is the array of items to sort using those keys. Here, for you, b is your keys and a is your items.

Thus:

Array.Sort(b, a);

will use the keys of b to sort the items of a.

I want to sort c by b's index -> c = {"1", "b", "u", "r", "a", "s"}

Not clear exactly what you mean. At the same time as you sort a using b? If so, it's easy as we can still use the above. Zip a and c into a single array of Tuple<int, string>.

var d = a.Zip(c, (x, y) => Tuple.Create(x, y)).ToArray();

Then:

Array.Sort(b, d);

as above. Then extract the pieces:

a = d.Select(z => z.Item1).ToArray();
c = d.Select(z => z.Item2).ToArray();

Alternatively, if you need to sort a lot of arrays using the same set of keys:

int[] indexes = Enumerable.Range(0, b.Length).ToArray();
Array.Sort(b, indexes);

Now you can use indexes to sort all the arrays you need. For example:

a = indexes.Select(index => a[index]).ToArray();
c = indexes.Select(index => c[index]).ToArray();

etc. as needed.

Possibly some minor coding errors here. No compiler handy.

Sorting two corresponding arrays

Rather than sort the arrays, sort the indices. I.e., you have

int arr[5]={4,1,3,6,2}
string arr1[5]={"a1","b1","c1","d1","e1"};

and you make

int indices[5]={0,1,2,3,4};

now you make a sort indices comparator that looks like this (just and idea, you'll probably have to fix it a little)

class sort_indices
{
private:
int* mparr;
public:
sort_indices(int* parr) : mparr(parr) {}
bool operator()(int i, int j) const { return mparr[i]<mparr[j]; }
}

now you can use the stl sort

std::sort(indices, indices+5, sort_indices(arr));

when you're done, the indices array will be such that arr[indices[0]] is the first element. and likewise arr1[indices[0]] is the corresponding pair.

This is also a very useful trick when you're trying to sort a large data object, you don't need to move the data around at every swap, just the indices.

How to sort two arrays with one being sorted based on the sorting of the other?

Pair Class could do the trick here.

import java.util.*;
public class Main
{
static class Pair implements Comparable<Pair>
{
int a1;
int a2;
Pair (int a1, int a2) //constructor
{
this.a1 = a1;
this.a2 = a2;
}
public int compareTo(Pair other) //making it only compare a2 values
{
return this.a2 - other.a2;
}
}
public static void main(String[] args)
{
int[] A1 = {1,2,3,4,5,6,7,8,9,10};
int[] A2 = {1,2,3,0,2,1,1,0,0,0};
Pair[] pairs = new Pair[A1.length];
for (int i = 0; i < pairs.length; i++)
{
pairs[i] = new Pair(A1[i], A2[i]);
}
Arrays.sort(pairs);
//printing values
for (int i = 0; i < A1.length; i++)
{
System.out.print(pairs[i].a1 + " ");
}
System.out.println();
for (int i = 0; i < A2.length; i++)
{
System.out.print(pairs[i].a2 + " ");
}
}
}

By making a Pair class that holds 2 variables a1 and a2, you can override the compareTo method to only compare the a2 value, so that when Arrays.sort is called, the pairs in the Pair array will be swapped only according to the a2 values. You can then access the values in the pairs and print them out. This will produce your desired output.

Sorting multiple arrays based on one

Use a hash as your intuition was leading you to:

 var scores = [2, 5, 3, 1, 4];var countries = ["Canada", "Macau", "Sweden", "France", "China"];
var score = {};for( var i=0,n=scores.length; i<n; i++){ score[scores[i]] = countries[i];}
for( var key in keys=Object.keys(score).sort() ){ var prop = keys[key]; console.log(prop, score[prop]);}

PHP - Sort Two Arrays The Same Way

http://php.net/manual/en/function.array-multisort.php

using example #1 in the reference:

$a = array('Bob', 'Sue', 'Phil', 'Jenny');
$b = array(15, 12, 13, 13);
array_multisort($a, $b);
print_r($a);
> Array
(
[0] => Bob
[1] => Jenny
[2] => Phil
[3] => Sue
)
print_r($b);
> Array
(
[0] => 15
[1] => 13
[2] => 13
[3] => 12
)

How to sort two arrays in the same way?

first make sure letters list contain data in correct order, in your question at second position in digits you have 1.1 and in letters you have two, which seems a mistake to me

    var letters = arrayOf("two", "one", "three")
var digits = arrayOf(2.36, 1.1, 3.0)

val x = digits.zip(letters).toMap().toSortedMap { o1, o2 -> o2.compareTo(o1)}
val keys = x.keys.toList() // [3.0, 2.36, 1.1]
val values = x.values.toList() // [three, two, one]

if you have large data set and don't want to waste memory on in-flight data structures (Pairs, List etc) then you can directly build a SortedMap

val x = emptyMap<Double, String>().toSortedMap{ o1, o2 -> o2.compareTo(o1)}
digits.forEachIndexed{index, value ->
x[value] = letters[index]
}

Sort two arrays based on the length of one

You could take the indices, sort them and map the values for both arrays.

var array1 = ['maximilian', 'moritz', 'hans'],    array2 = [5, 1, 2000],    indices = array1.map((_, i) => i);    indices.sort((a, b) => array1[a].length - array1[b].length);
array1 = indices.map(i => array1[i]);array2 = indices.map(i => array2[i]);
console.log(array1);console.log(array2);
.as-console-wrapper { max-height: 100% !important; top: 0; }


Related Topics



Leave a reply



Submit