Is there a way to fold with index in Rust? - indexing

In Ruby, if I had an array a = [1, 2, 3, 4, 5] and I wanted to get the sum of each element times its index I could do
a.each.with_index.inject(0) {|s,(i,j)| s + i*j}
Is there an idiomatic way to do the same thing in Rust? So far, I have
a.into_iter().fold(0, |x, i| x + i)
But that doesn't account for the index, and I can't really figure out a way to get it to account for the index. Is this possible and if so, how?

You can chain it with enumerate:
fn main() {
let a = [1, 2, 3, 4, 5];
let b = a.into_iter().enumerate().fold(0, |s, (i, j)| s + i * j);
println!("{:?}", b); // Prints 40
}

Related

Is there any operation to multiply each element in the first array to each element in the second array in Kotlin?

Is there any function (like fold, map, filter), which gets 2 arrays and lambda-function (for example multiplication) as parameters and returns third array?
I've used cycle for, but is there more beautiful method?
Yes, there is zip (nice example at the bottom of the page), see this (different) example:
fun main() {
val a = arrayOf( 1, 2, 3, 4 )
val b = arrayOf( 1, 2, 3, 4 )
val c = a.zip(b) { i, j -> i * j }
println(c)
}
which outputs
[1, 4, 9, 16]
There isn't a built in specifically but you can do this:
array1.zip(array2).map { (x,y) -> x*y }

Kotlin Array Slice Indexing

Let's say I want to iterate through all but the first element in Kotlin IntArray. Currently, I'm doing it like this:
fun minimalExample(nums: IntArray): Unit {
for(num in nums.sliceArray(IntRange(1,nums.size-1))) println(num)
}
Is there an easy syntax for doing this like in Python (I don't want to have to specify the ending index of the nums array):
for (num in nums[1:])
I think you could use Kotlin's drop which will remove the first n elements of an array.
fun minimalExampleWithDrop(nums: IntArray): Unit {
for(num in nums.drop(1)) println(num)
}
minimalExampleWithDrop(intArrayOf(1,2,3,4,5,6))
// 2
// 3
// 4
// 5
// 6
Repl.it:
https://repl.it/repls/SvelteShadyLivecd
You can alternatively also use the slice method which is present in lists and arrays. Here are examples for both:
val a = listOf(1, 2, 3, 4)
println(a.slice(1..a.size - 1))
val b = arrayOf(1, 2, 3, 4, 5, 6, 7, 8, 9)
println(b.slice(4..5))
This will print out:
[2, 3, 4]
[5, 6]
A basic for loop with 1 as starting index
val myList = intArrayOf(1,2,3,4,5,6)
for(i in 1 until myList.size){
Log.d(TAG,"${myList[i]}")
}
Or since it's an IntArray you can use it as an Iterator and skip elements like shown here
val iterator = myList.iterator()
// skip an element
if (iterator.hasNext()) {
iterator.next()
}
iterator.forEach {
Log.d(TAG,"it -> $it")
}
Just to add to #gil.fernandes answer, you can use slice with until like this:
val list = arrayOf(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
println(list.slice(0 until 5))
This will output:
[0, 1, 2, 3, 4]

Swift enumerated equivalent in Kotlin

In a 3x3 matrix representation, i can find the sum of both diagonals with one liners in Swift as below,
let array = [
[1, 2, 3],
[4, 5, 6],
[-7, 8, 9]
]
let d1 = array.enumerated().map({ $1[$0] }).reduce(0, +)
let d2 = array.reversed().enumerated().map({ $1[$0] }).reduce(0, +)
print(d1) // prints 15
print(d2) // prints 1
I am able to find map and reduce equivalents in Kotlin as flatMap and fold but couldn't find for enumerated.
How can we achieve similar with higher order functions in Kotlin?
Starting with this input:
val input: Array<Array<Int>> = arrayOf(
arrayOf(1, 2, 3),
arrayOf(4, 5, 6),
arrayOf(-7, 8, 9)
)
this is how I'd phrase the diagonal sums:
val mainDiagonalSum = input.indices
.map { input[it][it] }
.reduce(Int::plus)
val counterDiagonalSum = input.indices
.map { input[input.size - 1 - it][it] }
.reduce(Int::plus)
Note that this is an improvement over your solution because it doesn't have to create the reversed array. It improves the time complexity from O(n2) to O(n).
If you're dealing with large matrices, it would pay to reduce the space complexity from O(n) to O(1) as well, by using fold instead of reduce:
val mainDiagonalSum = input.indices
.fold(0) { sum, i -> sum + input[i][i] }
val counterDiagonalSum = input.indices
.fold(0) { sum, i -> sum + input[input.size - 1 - i][i] }
It looks like you're looking for withIndex

Remove only the trailing elements of a Vec that match a condition

I have a Vec<T> that has elements matching a pattern. I want to remove all trailing instances of the elements that match the pattern.
For example, I have a Vec<i32> and the pattern is (|x| x == 0). If the input was: vec![0, 1, 0, 2, 3, 0, 0], the output should be: vec![0, 1, 0, 2, 3]
To do this I tried:
fn main() {
let mut vec = vec![0, 1, 0, 2, 3, 0, 0];
vec = vec.into_iter().rev().skip_while(|&x| x == 0).rev();
}
But I get these compiler errors:
error[E0277]: the trait bound `std::iter::SkipWhile<std::iter::Rev<std::vec::IntoIter<{integer}>>, [closure#src/main.rs:3:44: 3:55]>: std::iter::DoubleEndedIterator` is not satisfied
--> src/main.rs:3:57
|
3 | vec = vec.into_iter().rev().skip_while(|&x| x == 0).rev();
| ^^^ the trait `std::iter::DoubleEndedIterator` is not implemented for `std::iter::SkipWhile<std::iter::Rev<std::vec::IntoIter<{integer}>>, [closure#src/main.rs:3:44: 3:55]>`
error[E0308]: mismatched types
--> src/main.rs:3:11
|
3 | vec = vec.into_iter().rev().skip_while(|&x| x == 0).rev();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `std::vec::Vec`, found struct `std::iter::Rev`
|
= note: expected type `std::vec::Vec<{integer}>`
found type `std::iter::Rev<std::iter::SkipWhile<std::iter::Rev<std::vec::IntoIter<{integer}>>, [closure#src/main.rs:3:44: 3:55]>>`
The strange thing is that DoubleEndedIterator is implemented for SkipWhile. In fact, SkipWhile even implements rev(). See here.
What am I doing wrong? Is there a better approach?
The iterator adaptor for reversal only works for iterators which can be traversed from any of the two ends (as in, it is a DoubleEndedIterator). While this is the case for the original one, this is no longer possible from the moment we include skip_while. In order to follow that approach, you would have to collect the rest of the reversed vector, and only then reverse again.
I, on the other hand, would just choose to fetch the index of the first trailing zero and truncate the vector with it.
let mut vec = vec![0, 1, 0, 2, 3, 0, 0];
if let Some(i) = vec.iter().rposition(|x| *x != 0) {
let new_len = i + 1;
vec.truncate(new_len);
}
... or just grab a slice instead:
let piece = &vec[..new_len];
Playground
As the error messages state:
the trait DoubleEndedIterator is not implemented for SkipWhile<...> — Take a look at the implementation of SkipWhile:
pub struct SkipWhile<I, P> {
iter: I,
flag: bool,
predicate: P,
}
You cannot reverse an iterator built from SkipWhile because it has no way of tracking if the "current" item was skipped when you add in the ability to pull from the front and the back.
expected struct Vec, found struct Rev — You still have an iterator, but you are trying to store it where a Vec must be stored. You cannot put a type A where a type B is needed.
I would collect the vector and then reverse it in place:
fn main() {
let mut vec = vec![0, 1, 0, 2, 3, 0, 0];
vec = vec.into_iter().rev().skip_while(|&x| x == 0).collect();
vec.reverse();
println!("{:?}", vec);
assert_eq!(vec, [0, 1, 0, 2, 3]);
}
DoubleEndedIterator is implemented for SkipWhile.
This is not true. If you look at the documentation for SkipWhile, it does not list that it implements DoubleEndedIterator. Here's an example of a trait it does implement: FusedIterator.
In fact, SkipWhile even implements rev()
It doesn't actually. Iterator::rev is only implemented in the condition that Self (which is SkipWhile) implements DoubleEndedIterator, which this doesn't:
fn rev(self) -> Rev<Self>
where
Self: DoubleEndedIterator,
Just to get things started, here is a really dodgy solution:
fn main() {
let mut vec = vec![0, 1, 0, 2, 3, 0, 0];
vec = vec.into_iter().rev().skip_while(|&x| x == 0).collect();
vec = vec.into_iter().rev().collect();
}

Unweave sequence, Kotlin functional/streaming idiom

I have a sequence of interleaved data (with fixed stride) and I'd like to reduce it to a single value for each "structure" (n*stride values to n values).
I could just use loop writing into the mutable list with selected step for reader index, but I'm looking for more functional and readable approach. Any thoughts?
For example:
Input sequence consists of RGB triplets (stride 3) and output is grayscale.
Imperative way is like:
fun greyscale(stream:List<Byte>):List<Byte>{
val out = ArrayList(stream.size / 3)
var i = 0; var o = 0
while(i < stream.size)
out[o++]=(stream[i++] + stream[i++] + stream[i++])/3
return out
}
How can I make something like that without explicitly implementing a function and mutable container, but purely on functional extensions like .map and so on?
Kotlin 1.2 (Milestone 1 was released yesterday) brings the chunked method on collections. It chunks up the collection into blocks of a given size. You can use this to implement your function:
fun greyscale(stream: List<Byte>): List<Byte> =
stream.chunked(3)
.map { (it.sum() / 3).toByte() }
A possible way would be grouping by the index of the elements (in this case /3) and mapping these groups to their sum.
stream.withIndex()
.groupBy { it.index / 3 }
.toSortedMap()
.values
.map { (it.sumBy { it.value } / 3).toByte() }
Also strictly functional, but using Rx, would be possible by using window(long)
Observable.from(stream)
.window(3)
.concatMap { it.reduce(Int::plus).toObservable() }
.map { (it / 3).toByte() }
Similar to #marstran's answer, in Kotlin 1.2 you can use chunked function, but providing the transform lambda to it:
fun greyscale(stream: List<Byte>): List<Byte> =
stream.chunked(3) { it.average().toByte() }
This variant has an advantage that it doesn't instantiate a new List for every triple, but rather creates a single List and reuses it during the entire operation.
Excludes remaining elements:
const val N = 3
fun greyscale(stream: List<Byte>) = (0 until stream.size / N)
.map { it * N }
.map { stream.subList(it, it + N).sum() / N }
.map(Int::toByte)
Output
[1, 2, 3, 4, 5, 6] => [2, 5]
[1, 2, 3, 4, 5] => [2]
Includes remaining elements:
const val N = 3
fun greyscale(stream: List<Byte>) = (0 until (stream.size + N - 1) / N)
.map { it * N }
.map { stream.subList(it, minOf(stream.size, it + N)).sum() / N }
.map(Int::toByte)
Output
[1, 2, 3, 4, 5, 6] => [2, 5]
[1, 2, 3, 4, 5] => [2, 3]
Best what I'm capable of is this:
fun grayscale(rgb:List<Byte>):List<Byte>
= rgb.foldIndexed(
IntArray(rgb.size / 3),
{ idx, acc, i ->
acc[idx / 3] = acc[idx / 3] + i; acc
}).map{ (it / 3).toByte() }
Output
in: [1, 2, 3, 4, 5, 6]
out: [2, 5]
And variations with ArrayList with add and last