How to specify starting value of index in Groovy's eachWithIndex method? - loops

When using Groovy's eachWithIndex method the index value starts at 0, I need it to start at 1. How can I do that?

The index will always start from 0
Your options are:
1) Add an offset to the index:
int offs = 1
list.eachWithIndex { it, idx ->
println "$it # pos ${idx + offs}"
}
2) Use something other than eachWithIndex (ie: transpose a list of integers starting at 1 with your original list, and then loop through this)
3) You can also use default parameters to hack this sort of thing in... If we pass eachWithIndex a closure with 3 parameters (the two that eachWithIndex is expecting and a third with a default value of index + 1):
[ 'a', 'b', 'c' ].eachWithIndex { item, index, indexPlusOne = index + 1 ->
println "Element $item has position $indexPlusOne"
}
We will give the output:
Element a has position 1
Element b has position 2
Element c has position 3

I wouldn't use eachWithIndex at all, a for loop with .indexed(1) will be more elegant/readable:
for (item in ['a','b','c','d','e'].indexed(1)) {
println("element $item.key = $item.value")
}
outputs:
element 1 = a
element 2 = b
element 3 = c
element 4 = d
element 5 = e
caveat -- indexed(n) is only available in Groovy 2.4.0 onwards

What about just using a Range?
def offset = 1
def arr = [1,2,3,4,5]
def len = arr.size() - 1
arr[offset..len].eachWithIndex{n,i -> println "${i+offset}:$n"}

You could use some metaprogramming hackery as well:
def eachWithMyIndex = { init, clos ->
delegate.eachWithIndex { it, idx -> clos(it, idx + init) }
}
List.metaClass.eachWithMyIndex = eachWithMyIndex
[1,2,3].eachWithMyIndex(10) {n, idx -> println("element $idx = $n") }
gives output:
element 10 = 1
element 11 = 2
element 12 = 3

Related

Why am I getting a Fatal error when I try removing an element from array inside a loop?

I have an array, I want to do some filtering in it, however, it gives me a runtime error. Is there any alternative way of doing this? (without using closures)
var arr = [4,5,6,7]
for i in 0..<arr.count - 1 {
if arr[i] > 2 {
arr.remove(at: i)
}
}
print(arr)
Think about what your code does.
if arr[i] > 2 { //#2
arr.remove(at: i)
}
}
At #1, it looks at the current number of elements in the array and sets the end value of the loop to 3. So the loop will run from 0 to 3.
At #2, each element in the array is greater than 2, so it gets removed from the array.
At i == 0 the 4 is removed. Now there are 3 elements
At i == 1, the
5 is removed. Now there are 2 elements
At i == 2, it attempts to
fetch an element at index 2, and crashes with an index out of range
error.
You are mutating the array as you attempt to iterate through it. Don't do that.
As others have said, use filter instead:
arr = arr.filter { $0 <= 2 }
If you really want to use a for loop and remove elements via index, loop through the array backwards:
var arr = [4,5,6,7]
for index in stride(from: arr.count-1, to: -1, by: -1) {
let thisValue = arr[index]
print("arr[\(index)]=\(thisValue)")
if thisValue > 2 {
arr.remove(at: index)
print("->> removing \(thisValue) from arr at index \(index)")
}
}
print("\nAfter for loop, arr contains \(arr.count) items")
arr.forEach {
print($0)
}
That ouputs:
arr[3]=7
->> removing 7 from arr at index 3
arr[2]=6
->> removing 6 from arr at index 2
arr[1]=5
->> removing 5 from arr at index 1
arr[0]=4
->> removing 4 from arr at index 0
After for loop, arr contains 0 items
This is a great example of why mutation is best avoided.
If you're manipulating an array and iterating over it at the same time, the index values are going to be invalid, because what was at index 4, will now be at index 3 if you delete something at position 1.
You can do it without 'using closures':
var idxToRemove: [Int] = []
for (idx, i) in arr.enumerated() {
if i > 2 {
idxToRemove.append(idx)
}
}
for i in idxToRemove.reversed() {
arr.remove(at: i)
}
But what you want is: let arr = [4,5,6,7].filter { $0 <= 2 }
var arr = [4, 5, 6, 7]
arr = arr.filter { $0 <= 2 }
print(arr)

How can I find the nonzero values in a MATLAB cells array?

The following code generates an cell array Index [1x29], where each cell is an array [29x6]:
for i = 1 : size(P1_cell,1)
for j = 1 : size(P1_cell,2)
[Lia,Lib] = ismember(P1_cell{i,j},PATTERNS_FOR_ERANOS_cell{1},'rows');
Index1(i,j) = Lib % 29x6
end
Index{i} = Index1; % 1x29
end
How can I find the nonzero values in Index array?, i.e. generate an array with the number of non-zero values in each row of the Index1 array. I tried the following loop, but it doesn't work, it creates conflict with the previous one:
for i = 1 : length(Index)
for j = 1 : length(Index)
Non_ceros = length(find(Index{:,i}(j,:))); %% I just need the length of the find function output
end
end
I need help, Thanks in advance.
The nnz() (number of non-zeros) function can be used to evaluate the number of non-zero elements. To obtain the specific positive values you can index the array by using the indices returned by the find() function. I used some random test data but it should work for 29 by 6 sized arrays as well.
%Random test data%
Index{1} = [5 2 3 0 zeros(1,25)];
Index{2} = [9 2 3 1 zeros(1,25)];
Index{3} = [5 5 5 5 zeros(1,25)];
%Initializing and array to count the number of zeroes%
Non_Zero_Counts = zeros(length(Index),1);
for Row_Index = 1: length(Index)
%Evaluating the number of positive values%
Array = Index{Row_Index};
Non_Zero_Counts(Row_Index) = nnz(Array);
%Retrieving the positive values%
Positive_Indices = find(Array);
PositiveElements{Row_Index} = Array(Positive_Indices);
disp(Non_Zero_Counts(Row_Index) + " Non-Zero Elements ");
disp(PositiveElements{Row_Index});
end
Ran using MATLAB R2019b
for i = 1 : length(Index)
for j = 1 : length(Index)
Non_ceros(i,j) = nnz(Index{:,i}(j,:));
end
end

Comparing every element in a list with each other and printing a pattern

I defined a list :
my_list = [1,34,56,78,97,889]
Each element should be compared and have printed its left least value.
For example: comparing 1 and 34, 1 is less than 34, so append into a new list and so on until the last element in the list.
My code is:
lio = [1,34,56,78,97,889]
i = 0
liu = []
while i <= len(lio) - 1:
if lio[i] < (lio[i + 1]) - 1:
liu.append(lio[i])
print(liu)
i = i + 1
When I run it, it prints until 97, after that it shows list index out of range.
Use enumerate
Ex:
lio = [1,34,56,78,97,889]
i = 0
liu = []
l = len(lio)
for i, v in enumerate(lio):
if i+1 == l: #Check if end of list
continue #Skip processing
if v < (lio[i + 1]):
liu.append(v)
print(liu)
i = i + 1

How to find the index of the last array element

In a situation where you have to deal with array indices (and can't just use an enumerator), how do you find the index of the last element?
These two options come to mind, but I'm hoping there's an answer that is more self documenting (like Array#last(), but for the index instead of the element):
a = [0, 1, 2, 3]
# option 1
last_index = a.length - 1
# option 2
last_index = a.rindex { true }
arr = [1,2,3,4,5,6]
def last_index(arr)
counter = -1
arr.each do |i|
i
counter += 1
end
counter
end
last_index(arr)

I have to put sorted list and sorted array into dictionary

How do I put values from a sorted list and array into a dictionary and determine how many time numbers repeat themselves? This is my code so far.
from numpy import *
from random import *
lista=[]
for x in range(0,20):
broj=input("Unesi %d broj>>" % (x+1))
lista.append(broj)
print"Nesortirana lista>>",lista
while True:
ne=False
for b in range(0,len(lista)-1):
if lista[b] > lista[b+1]:
pomocna=lista[b]
lista[b]=lista[b+1]
lista[b+1]=pomocna
ne=True
if ne == False:
break
print "Sortirana lista",lista
velicina_polja = 10
polje = array(velicina_polja * [0])
for i in range(0, velicina_polja):
polje[i] = randrange(1, 11)
print "Nesortirano polje:", polje
ima_promjene = True
while ima_promjene:
ima_promjene = False
for i in range(0, velicina_polja - 1):
if polje[i] > polje[i + 1]:
polje[i], polje[i + 1] = polje[i + 1], polje[i]
ima_promjene = True
print "Sortirano polje:", polje
I think you want something like this:
#!/usr/bin/env python
if __name__ == "__main__":
my_list = [ 1, 2, 3, 3]
my_dict = {}
for item in my_list:
my_dict[item] = my_dict.get(item, 0) + 1
for key in my_dict.keys():
print key, ":", my_dict[key]
It adds one to the count for a given key. If the key is not already in the dictionary, it assumes a value of zero and then increments that.
So the above example prints:
1 : 1
2 : 1
3 : 2

Resources