Using Each_With_Index with Map

How to map/collect with index in Ruby?

If you're using ruby 1.8.7 or 1.9, you can use the fact that iterator methods like each_with_index, when called without a block, return an Enumerator object, which you can call Enumerable methods like map on. So you can do:

arr.each_with_index.map { |x,i| [x, i+2] }

In 1.8.6 you can do:

require 'enumerator'
arr.enum_for(:each_with_index).map { |x,i| [x, i+2] }

Using each_with_index with map

a.to_enum.with_index(1).map { |element, index| "#{index}. #{element}" }

or

a.map.with_index(1) { |element, index| "#{index}. #{element}" }

with_index(1) makes the index of the first element 1.

In the first solution the array is converted to an enum, and in the second solution the array is directly mapped.

Enumerate or map through a list with index and value in Dart

There is a asMap method which converts the list to a map where the keys are the index and values are the element at index. Please take a look at the docs here.

Example:

List _sample = ['a','b','c'];
_sample.asMap().forEach((index, value) => f);

eachWithIndex loop is unstable

result?.data is instance of list (look at the data class after "as Map" operation it becomes ArrayList1_groovyProxy...)
You can iterate through list(and build the map if you need):

Map data = [:]
result?.data?.eachWithIndex { dataItem, idx ->
if (dataItem) {
log.info dataItem
data[idx] = dataItem
}
}

If this happends time to time - probably your result?.data already comes sometimes as List and sometimes as Map

Groovy: Different behaviour observed using the eachWithIndex method

When you use the no-arg version of eachWithIndex, it is the current entry in the Map. That means that it.key and it.value return what you expect.

When you use the two-arg version of eachWithIndex, again, it is the current entry in the Map and i is the current index. You're printing i, the index, and then since you are only printing it, you are getting the result of it.toString(), which formats the map entry as "${it.key}=${it.value}"

Loop through Map in Groovy?

Quite simple with a closure:

def map = [
'iPhone':'iWebOS',
'Android':'2.3.3',
'Nokia':'Symbian',
'Windows':'WM8'
]

map.each{ k, v -> println "${k}:${v}" }

Ruby : Choosing between each, map, inject, each_with_index and each_with_object

A more tl;dr answer:

How to choose between each, map, inject, each_with_index and each_with_object?

  • Use #each when you want "generic" iteration and don't care about the result. Example - you have numbers, you want to print the absolute value of each individual number:

    numbers.each { |number| puts number.abs }
  • Use #map when you want a new list, where each element is somehow formed by transforming the original elements. Example - you have numbers, you want to get their squares:

    numbers.map { |number| number ** 2 }
  • Use #inject when you want to somehow reduce the entire list to one single value. Example - you have numbers, you want to get their sum:

    numbers.inject(&:+)
  • Use #each_with_index in the same situation as #each, except you also want the index with each element:

    numbers.each_with_index { |number, index| puts "Number #{number} is on #{index} position" }
  • Uses for #each_with_object are more limited. The most common case is if you need something similar to #inject, but want a new collection (as opposed to singular value), which is not a direct mapping of the original. Example - number histogram (frequencies):

    numbers.each_with_object({}) { |number, histogram| histogram[number] = histogram[number].to_i.next }

EachWithIndex groovy statement

These are plain methods but they follow quite a specific pattern - they take a Closure as their last argument. A Closure is a piece of functionality that you can pass around and call when applicable.

For example, method eachWithIndex might look like this (roughly):

void eachWithIndex(Closure operation) {
for (int i = 0; this.hasNext(); i++) {
operation(this.next(), i); // Here closure passed as parameter is being called
}
}

This approach allows one to build generic algorithms (like iteration over items) and change the concrete processing logic at runtime by passing different closures.

Regarding the parameters part, as you see in the example above we call the closure (operation) with two parameters - the current element and current index. This means that the eachWithIndex method expects to receive not just any closure but one which would accept these two parameters. From a syntax prospective one defines the parameters during closure definition like this:

{ elem, index ->
// logic
}

So -> is used to separate arguments part of closure definition from its logic. When a closure takes only one argument, its parameter definition can be omitted and then the parameter will be accessible within the closure's scope with the name it (implicit name for the first argument). For example:

[1,2,3].each {
println it
}

It could be rewritten like this:

[1,2,3].each({ elem ->
println elem
})

As you see the Groovy language adds some syntax sugar to make such constructions look prettier.

Groovy eachWithIndex multiple statements

The following code:

[1,2,3,4,5,6,7].eachWithIndex { num, idx ->  
int a = 2
int b = 3
println "${a + b} ${idx}: ${num}"
}

emulates your example, works, and produces the following output:

~> groovy solution.groovy 
5 0: 1
5 1: 2
5 2: 3
5 3: 4
5 4: 5
5 5: 6
5 6: 7

~>

You don't need the second level of curly braces. Also in your code you have misspelled int as nt, you don't need the semicolons at the line endings, and in general groovy string interpolation is more readable than appending to the string using +.

To generate a list for each map key as iterating through list?

You can create a map using [ key: value] notation. Since your value is an array of two elements you can simply create it using [element1,element2] notation, and then you can add the object to the map using << operator.

So this myMap << [ (object) : [element1,element2]] can do the job.

In your code:

   def myMap = [:]
anotherList.each{
object -> //here i do some work to get two elements
def element1 = ..
def element2 = ..

// so here i need to generate a list for the two elements with index 0 and 1
myMap << [ (object) : [element1,element2]]
}
return myMap

Note that I use (object) to evaluate the key, because if I use directly object the literal is used as key in the map instead of the value.

Hope this helps,

UPDATED BASED ON OP COMMENT:

If I understand well your requirements you want that map keys are the index instead of the value isn't it? To do so you can use eachWithIndex instead of each for example:

def myMap = [:]
def anotherList = ['a','b','c','d']
anotherList.eachWithIndex{ object,index -> //here i do some work to get two elements
def element1 = object + 'z'
def element2 = object + 'x'

// so here i need to generate a list for the two elements with index 0 and 1
myMap << [ (index) : [element1,element2]]
}
return myMap //Result: [0:[az, ax], 1:[bz, bx], 2:[cz, cx], 3:[dz, dx]]


Related Topics



Leave a reply



Submit