Can't Form Range with End < Start Check Range Before Doing for Loop

Can't form Range with end start Check range before doing for loop?

If you just want to iterate over a collection, then use the for <element> in <collection> syntax.

for element in arr {
// do something with element
}

If you also need access to the index of the element at each iteration, you can use enumerate(). Because indices are zero based, the index will have the range 0..<arr.count.

for (index, element) in arr.enumerate() {

// do something with index & element

// if you need the position of the element (1st, 2nd 3rd etc), then do index+1
let position = index+1
}

You can always add one to the index at each iteration in order to access the position (to get a range of 1..<arr.count+1).

If none of these solve your problem, then you can use the range 0..<arr.count to iterate over the indices of your array, or as @vacawama says, you could use the range 1..<arr.count+1 to iterate over the positions.

for index in 0..<arr.count {

// do something with index
}

for position in 1..<arr.count+1 {

// do something with position
}

0..<0 cannot crash for an empty array as 0..<0 is just an empty range, and 1..<arr.count+1 cannot crash for an empty array as 1..<1 is also an empty range.

Also see @vacawama's comment below about using stride for safely doing more custom ranges. For example (Swift 2 syntax):

let startIndex = 4
for i in startIndex.stride(to: arr.count, by: 1) {
// i = 4, 5, 6, 7 .. arr.count-1
}

Swift 3 syntax:

for i in stride(from: 4, to: arr.count, by: 1) {
// i = 4, 5, 6, 7 .. arr.count-1
}

This is where startIndex is the number to start the range at, arr.count is the number that the range will stay below, and 1 is the stride length. If your array has less elements than the given starting index, then the loop will never be entered.

Can't form Range with end start

Your for has two problems:

  1. If slashList.count is 0 (because slashList is empty), it would try to count from 1 to 0 adding 1 (which results in an infinite loop), that's why the compiler gives you the error start > end.
  2. if slashList.count is greater than 0 (slashList is not empty), it would use an index which is out of bounds, because you count from 1 to slashList.count, while the indexes go from 0 to slashList.count - 1

to check all indexes it should be:

for i in 0 ..< slashList.count { 
// your code
}

to ignore the first element (index 0) do:

for i in 1 ..< slashList.count {
// your code
}

for your special case, it would seem better to me to do something like:

for element in slashList {    
if !quotaList.contains(element+1)
{
slashList.removeObject(element)
}
}

You can use removeObject from this answer. If, for some reason, you also need the index, do:

for (index, element) in slashList.enumerate() {
// your code
}

Swift fatal error: Can't form Range with end start


for in (0...row-1).reverse()

Swift can't read row-1...0

Why does range(start, end) not include end?

Because it's more common to call range(0, 10) which returns [0,1,2,3,4,5,6,7,8,9] which contains 10 elements which equals len(range(0, 10)). Remember that programmers prefer 0-based indexing.

Also, consider the following common code snippet:

for i in range(len(li)):
pass

Could you see that if range() went up to exactly len(li) that this would be problematic? The programmer would need to explicitly subtract 1. This also follows the common trend of programmers preferring for(int i = 0; i < 10; i++) over for(int i = 0; i <= 9; i++).

If you are calling range with a start of 1 frequently, you might want to define your own function:

>>> def range1(start, end):
... return range(start, end+1)
...
>>> range1(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Is there a short way to check array size before going into for loop?

Drop the initial condition:

for i in 0..<json.count {
// Do something
}

If the range in the loop is impossible the code will not get executed.

Also, if you don't use i inside the brackets you can replace it with _.

Can range-based for loops be aware of the end?

The very purpose of range-based for loops is to forget the iterator. As such, they only allow you access to the current value and not the iterator. Would the following code do it for you?

set<int> S = {1,2,3,4};

std::string output;
for(auto &x: S) {
if (!output.empty())
output += ",";
output += to_string(x);
}

cout << output;

EDIT

Another solution: Instead of comparing iterators (as one would do with "normal" for loops), you could compare the addresses of the values:

set<int> S = {1,2,3,4};
auto &last = *(--S.end());
for (auto &x : S)
{
cout << x;
if (&x != &last)
cout << ",";
}


Related Topics



Leave a reply



Submit