I have this
var nlist = [4,2,1,5];
var compare = (a, b) => a.compareTo(b);
nlist.sort(compare);
print(nlist); // [1,2,4,5]
and here (where I changed the (b, a) to (a, b))
var nlist = [4,2,1,5]
var compare = (b, a) => a.compareTo(b);
nlist.sort(compare);
print(nlist); // [5,4,2,1]
Why does this little modification change from ascending to descending order?
For ascending
var nlist = [1, 6, 8, 2, 16, 0]
nlist.sort((a, b) => a.compareTo(b));
For descending
var nlist = [1, 6, 8, 2, 16, 0]
nlist.sort((b, a) => a.compareTo(b));
Would be interesting what you actually expected from happening after the change.
Compare returns +1, 0, -1 depending on whether the 2nd argument is greater than the 1st or 0 if they are equal. When you swap the two arguments +1 becomes -1 and vice versa this leads to a descending order instead of an ascending one.
1.compareTo(2)
returns -1 and
print(nlist.sort((a, b) => a.compareTo(b)));
prints the list elements in ascending order, so yes, ascending is default.
For Ascending:
var nlist = [4,2,1,5]
var compare = (b, a) => a.compareTo(b);
For Descending:
var compare = (b, a) => -a.compareTo(b);
Another way to sort
var nlist = [4,2,1,5];
var ascending = nlist..sort();
var descending = ascending.reversed;
print(ascending); // [1, 2, 4, 5]
print(descending); // [5, 4, 2, 1]
For ascending
There is no need to write list.sort((a, b) => a.compareTo(b));. This works:
list.sort();
For descending
list.sort((a, b) => b.compareTo(a));
Or, as of 2021, if you use https://pub.dev/packages/fast_immutable_collections (FIC package) this works:
list.sortReversed();
Notes:
(list..sort()).reversed does NOT reverse the list, in place. Instead, it sorts the original list in ascending order, and then returns a descending iterable, not a List (i.e., Iterable<int>, not List<int>). Maybe that's what you want. If not, you have to do list = (list..sort()).reversed.toList();. However, for large lists list.sortReversed() is much faster.
In the beforementioned FIC package there is also a reversedView() method, which returns a descending VIEW of the list. A "view" means if you later add items to the original list, the reversed one will also have those items, and vice-versa. So if your list is already sorted in ascending order and you want to have access to the descending list without wasting time doing the reversal, just do:
list.sort();
List<int> listDescending = list.reversedView; // Very fast.
Disclaimer: I am the author of the FIC package.
var nlist = [1, 6, 8, 2, 16, 0];
nlist.sort((a, b) => a - b);
Related
I am struggling to sort a list in a sorted fashion without actually "sorting" the list.
arr = [3, 2, 1, 4, 5]
count = 0
current = arr[0]
prev = -1
while count < len(arr):
for item in arr:
if current < item > prev:
current = item
prev = current
count = count + 1
print(current)
Output:
5
5
5
5
5
I don't want to sort the list. I am wondering is there a way to not sort the list and not change the original list and print the items in a sorted fashion?
It's pretty unclear what you're trying to do. If you want a sorted copy, you could make a list containing the indices of the the original objects ([0, 1, 2, ..., n]) and then sort these by comparing the original values at those indices, then map this sorted list back to the values from the first list.
But much simpler still is just to sort a shallow clone of the list.
If you read Javascript, here's a demonstration of that idea, using a simple range helper function to create the list of indices:
const arr = [8, 6, 7, 5, 3, 0, 9]
const range = (lo, hi) =>
[...Array (hi - lo)] .map((_, i) => lo + i)
const indexSort = (ns) =>
range (0, ns .length)
.sort ((i, j) => ns [i] - ns [j])
.map (x => ns [x])
console .log ('indexSort:', indexSort (arr))
console .log ('shallow clone:', [...arr] .sort ((a, b) => a - b))
console .log ('no mutation of original array:', arr)
.as-console-wrapper {max-height: 100% !important; top: 0}
I'm writing a LINQ query where I have to select the last result in a list.
Which is more efficient?
.OrderByDescending(x => x.Id).First();
or
.Last();
Neither can be said to be more efficient. They do different things.
.Last();
This one returns the last element of a sequence (if there is one), without ordering
.OrderByDescending(x => x.Id).First();
This one returns you the element that would be last if you'd order in ascending order, if there is one. It will give be the same result as:
.OrderBy(x => x.Id).Last();
var sequence = {4, 1, 3}
var a = sequence.Last(); // result: 3
var b = sequence.OrderByDescending(x => x.Id) // intermediate result: 4, 3, 1
.First(); // final result: 4
var c = sequence.OrderBy(x => x.Id) // intermediate result: 1, 3, 4
.Last(); // final result: 4
b is more efficient than c, because after ordering the enumerator only has to MoveNext to the first element, while for c the enumerator has to MoveNext(), until there are no more elements.
Given a list of non-sequential and unordered numbers is there an optimal means to index the list, where the ith element in the index is the position of the ith element in the indexed list if it were sorted.
So [45,2,6,33] would have index [4,1,2,3]
You can just sort the list and then create a dictionary / associative array mapping each element to its index in the sorted list. You could do this in a loop, or, in Python, even in a single line:
>>> lst = [45, 2, 6, 33]
>>> d = {x: i for (i, x) in enumerate(sorted(lst))}
>>> d
{2: 0, 6: 1, 33: 2, 45: 3}
Now use the values from the dictionary to create your result list:
>>> [d[x] + 1 for x in lst]
[4, 1, 2, 3]
If the list can contain duplicate numbers, and you don't want your result list to contain duplicate indices, you can map the values to lists of indices:
>>> lst = [45, 2, 6, 33, 6]
>>> d = {}
>>> for i, x in enumerate(sorted(lst)):
... d.setdefault(x, []).append(i)
>>> d
{2: [0], 6: [1, 2], 33: [3], 45: [4]}
Now, convert each of those lists to an iterator, and get the next index for each value in the original list.
>>> d2 = {x: iter(d[x]) for x in d}
>>> [next(d2[x]) + 1 for x in lst]
[5, 1, 2, 4, 3]
You can perform radix sort which uses counting sort as a sub-routine and can work in linear time complexity for large numbers as well. Time complexity will be O(n).
Then use a hashmap <element, position when sorted> to record the position of the elements in sorted list. At last print the corresponding position of input. Space complexity is O(n).
It seems that the problem you are facing is that how to keep the original position of element since after sorting the position would be lost. You need to link position in original array with the element and then sort. Following is the pseudo code
list of pair p[] as (element, original position)
for each index i in original input array A
p.push(A[i], i) //adding element and original position
Sort on basis of first element
q = sort(p)
Now q has element in its position after sorting. Second array should have this position on its index in original array
Let new array B is resultant array
for each index i in array q
B[q[i].second] = i //q[i].second is index in original array. so putting index of sorted array in that
Update: Some are not able to understand this algorithm so have put a code in JavaScript.
var input = [45,2,6,33];
var p = [];
for(var i = 0;i < input.length;i++)
{
p.push({first:input[i],second:i});
}
p.sort(function(a,b){
return a.first > b.first;
});
var B = Array(input.length);
for(var i = 0;i < p.length;i++)
{
B[p[i].second] = i;
}
console.log(B);
I am implementing an algorithm in scala where I have set of nodes (Integers numbers) and each node has one property associated with it, lets call that property "d" (which is again an integer).
I have a list[Int] , this list contains nodes in the descending order of value "d".
Also I have a Map[Int,Iterable[Int]] , here key is a node and value is the list of all its neighbors.
The question is, how can I store the List of neighbors for a node in Map in the descending order of property "d" .
Example :
List 1 : List[1,5,7,2,4,8,6,3] --> Imagine this list is sorted in some order and has all the numbers.
Map : [Int,Iterable][Int]] --> [1 , Iterable[2,3,4,5,6]]
This iterable may or may not have all numbers.
In simple words, I want the numbers in Iterable to be in same order as in List 1.
So my entry in Map should be : [1, Iterable[5,2,4,6,3]]
The easiest way to do this is to just filter the sorted list.
val list = List(1,5,7,2,4,8,6,3)
val map = Map(1 -> List(2,3,4,5,6),
2 -> List(1,2,7,8))
val map2 = map.mapValues(neighbors => list.filter(neighbors.contains))
println(map2)
Here is a possible solution utilizing foldLeft (note we get an ArrayBuffer at end instead of desired Iterable, but the type signature does say Iterable):
scala> val orderTemplate = List(1,5,7,2,4,8,6,3)
orderTemplate: List[Int] = List(1, 5, 7, 2, 4, 8, 6, 3)
scala> val toOrder = Map(1 -> Iterable(2,3,4,5,6))
toOrder: scala.collection.immutable.Map[Int,Iterable[Int]] = Map(1 -> List(2, 3, 4, 5, 6))
scala> val ordered = toOrder.mapValues(iterable =>
orderTemplate.foldLeft(Iterable.empty[Int])((a, i) =>
if (iterable.toBuffer.contains(i)) a.toBuffer :+ i
else a
)
)
ordered: scala.collection.immutable.Map[Int,Iterable[Int]] = Map(1 -> ArrayBuffer(5, 2, 4, 6, 3))
Here's what I got.
val lst = List(1,5,7,2,4,8,6,3)
val itr = Iterable(2,3,4,5,6)
itr.map(x => (lst.indexOf(x), x))
.toArray
.sorted
.map(_._2)
.toIterable // res0: Iterable[Int] = WrappedArray(5, 2, 4, 6, 3)
I coupled each entry with its relative index in the full list.
Can't sort iterables so went with Array (for no particular reason).
Tuples sorting defaults to the first element.
Remove the indexes.
Back to Iterable.
var cheapest = leaves.sort((a,b) => <boolean>(<number>a.cost < <number>b.cost));
//also tried without casting
Gives me the following error:
'Error'
message: 'Argument of type '(a: any, b: any) => boolean' is not assignable to parameter of type '(a: any, b: any) => number'.
Type 'boolean' is not assignable to type 'number'.'
How should i fix this?
Edit:
The js code ( original) is taken from :
https://github.com/atomicptr/goap/blob/gh-pages/gameplay/ai/planner.js , which indeed seems to sort by bool instead of number.
This is not how Array.sort works. You need to return a number, but the predicate you've given returns a boolean (The less than (<) operator results in true or false). The sort order is determined by whether the number your function returns is negative, positive, or zero. The MDN example illustrates this well with an example compare function.
function compare(a, b) {
if (a is less than b by some ordering criterion) {
return -1;
}
if (a is greater than b by the ordering criterion) {
return 1;
}
// a must be equal to b
return 0;
}
If you want to sort ascending you can do this with
var cheapest = leaves.sort((a,b) => a.cost - b.cost);
assuming that leaves is typed correctly so a and b have their types correctly inferred.
The comparator function of a sort should return -1, 0, or 1. Returning a boolean instead (effectively 1 or 0) will fail to sort the list correctly!
For example, in Chrome (sort implementations are host-dependent), this line:
[1, 2, 5, 6, 5, 5, 4, 3, 2, 1, 4, 2, 4, 6, 3].sort(function(a, b) { return a < b; })
Produces:
[3, 3, 5, 6, 5, 5, 4, 6, 4, 4, 2, 2, 2, 1, 1]
Which is not sorted!
You should write something like a > b ? 1 : a === b ? 0 : -1 instead
When using Array.prototype.sort(), a comparator function can be used to properly define sorting behaviour. According to the MDN Javascript documentation:
To compare numbers instead of strings, the compare function can simply subtract b from a.
Thus to sort the array 'leaves' in ascending order:
var cheapest = leaves.sort((a,b) => a.cost- b.cost);
With a Typescript generic:
var cheapest = leaves.sort((a,b) => <number>(a.cost- b.cost));