Reversing a Range results in Mismatching Types
You can use AnySequence
to create a "type-erased sequence"
which forwards the operations to the underlying sequence, hiding the specifics of the underlying SequenceType
:
let range = aNumber % 2 == 0
? AnySequence ( (0 ..< 10) )
: AnySequence ( (0 ..< 10).reverse() )
for i in range { print(i) }
Both expression in the ternary conditional operator have the
same type AnySequence<Int>
, so that is the type of range
.
For Swift 3 and later, replace reverse()
by reversed()
.
How to express either forward or backward ranges in Swift?
You need to use a type eraser. The standard library provides AnyCollection
, which does just the trick:
let range = forward ? AnyCollection((x+1)..<count) : AnyCollection((0..<x).reversed())
for i in range {
// ...
}
Print a list in reverse order with range()?
use reversed()
function:
reversed(range(10))
It's much more meaningful.
Update:
If you want it to be a list (as btk pointed out):
list(reversed(range(10)))
Update:
If you want to use only range
to achieve the same result, you can use all its parameters. range(start, stop, step)
For example, to generate a list [5,4,3,2,1,0]
, you can use the following:
range(5, -1, -1)
It may be less intuitive but as the comments mention, this is more efficient and the right usage of range for reversed list.
Why are reversed and sorted of different types in Python?
The difference is that reversed
is an iterator (it's also lazy-evaluating) and sorted
is a function that works "eagerly".
All built-in iterators (at least in python-3.x) like map
, zip
, filter
, reversed
, ... are implemented as classes. While the eager-operating built-ins are functions, e.g. min
, max
, any
, all
and sorted
.
>>> a = [1,2,3,4]
>>> r = reversed(a)
<list_reverseiterator at 0x2187afa0240>
You actually need to "consume" the iterator to get the values (e.g. list
):
>>> list(r)
[4, 3, 2, 1]
On the other hand this "consuming" part isn't needed for functions like sorted
:
>>> s = sorted(a)
[1, 2, 3, 4]
In the comments it was asked why these are implemented as classes instead of functions. That's not really easy to answer but I'll try my best:
Using lazy-evaluating operations has one huge benefit: They are very memory efficient when chained. They don't need to create intermediate lists unless they are explicitly "requested". That was the reason why map
, zip
and filter
were changed from eager-operating functions (python-2.x) to lazy-operating classes (python-3.x).
Generally there are two ways in Python to create iterators:
- classes that
return self
in their__iter__
method - generator functions - functions that contain a
yield
However (at least CPython) implements all their built-ins (and several standard library modules) in C. It's very easy to create iterator classes in C but I haven't found any sensible way to create generator functions based on the Python-C-API. So the reason why these iterators are implemented as classes (in CPython) might just be convenience or the lack of (fast or implementable) alternatives.
There is an additional reason to use classes instead of generators: You can implement special methods for classes but you can't implement them on generator functions. That might not sound impressive but it has definite advantages. For example most iterators can be pickled (at least on Python-3.x) using the __reduce__
and __setstate__
methods. That means you can store them on the disk, and allows copying them. Since Python-3.4 some iterators also implement __length_hint__
which makes consuming these iterators with list
(and similar) much faster.
Note that reversed
could easily be implemented as factory-function (like iter
) but unlike iter
, which can return two unique classes, reversed
can only return one unique class.
To illustrate the possible (and unique) classes you have to consider a class that has no __iter__
and no __reversed__
method but are iterable and reverse-iterable (by implementing __getitem__
and __len__
):
class A(object):
def __init__(self, vals):
self.vals = vals
def __len__(self):
return len(self.vals)
def __getitem__(self, idx):
return self.vals[idx]
And while it makes sense to add an abstraction layer (a factory function) in case of iter
- because the returned class is depending on the number of input arguments:
>>> iter(A([1,2,3]))
<iterator at 0x2187afaed68>
>>> iter(min, 0) # actually this is a useless example, just here to see what it returns
<callable_iterator at 0x1333879bdd8>
That reasoning doesn't apply to reversed
:
>>> reversed(A([1,2,3]))
<reversed at 0x2187afaec50>
Reversing a negative integer results in an unexpected result
You have set repeat = len(str(num))
before changing the sign of negative numbers and you should decrement it if num is negative. In your last iteration of for
loop (if num is negative), mod
will be always zero and hence, you will always get a zero appended if num is negative.
If I would be solving this problem, then I might have written it in this way:
def reverse(num):
sign = num >= 0 # True if num is +ve. False if num is -ve
num = abs(num)
repeat = len(str(num))
result = 0
for i in range(repeat):
mod = num % 10
num //= 10
result = result * 10 + mod
return result if sign else -result
print(reverse(123))
print(reverse(-123))
There is another way to solve this problem which is bit more compact:
def revdigits(num):
reverseStr = lambda s: "".join(reversed(s))
digits = reverseStr(str(num)) if num >= 0 else ("-" + reverseStr(str(num)[1:]))
return int(digits)
num = 123
print(revdigits(num))
print(revdigits(-num))
Output:
321
-321
How do I reverse a list or loop over it backwards?
To get a new reversed list, apply the reversed
function and collect the items into a list
:
>>> xs = [0, 10, 20, 40]
>>> list(reversed(xs))
[40, 20, 10, 0]
To iterate backwards through a list:
>>> xs = [0, 10, 20, 40]
>>> for x in reversed(xs):
... print(x)
40
20
10
0
Dynamically create a range in either direction in Rust
You can dynamically dispatch it. Wrapping them into a Box
and returning a dynamic object, an Iterator
in this case. For example:
fn maybe_reverse_range(init: usize, end: usize, reverse: bool) -> Box<dyn Iterator<Item=usize>> {
if reverse {
Box::new((init..end).rev())
} else {
Box::new((init..end))
}
}
Playground
Why does Collections.sort in reverse order resulted in incomplete sort?
Just like in the comments, try using Comparator.comparing(RecordingFile::getLastModfied).reversed()
instead of doing it manually.
If you decide to still do it manually, check the lastModfied
type because if it's a long
then you shouldn't be returning the final result of the comparison as int
Related Topics
How to Load Thousands Records to Realm Correctly
Cgaffinetransformmakerotation with Negative M_Pi
Displaying Instances of View Controllers Within Xcode Without Disturbing the Current Hierarchy
Multiple Image Pickers in One Controller
Change Selected Row Label Color in Picker View Swift 1.2
Using Huffman Coding to Compress Images Taken by the iPhone Camera
Navigationlink Inside Lazyvgrid Cycles All Entries on Back, Swiftui
Fbsdk (New Facebook Sdk 4.0) Implementation Is Not Working for Login with Facebook
How to Make Watchkit Extension App and My iPhone App Share the Same Icloud Databases
Swift How to Add Background Color Just Around Text in a Label
How to Position UI Elements on Background Image Relative to the Image
Change Push Notifications Programmatically in Swift
How to Open Amazon App from Within My App