zip with next value with kotlin Flow - kotlin

how to zip a Flow with the next value as zipWithNext operator for collections?
zipWithNext behaves like:
val letters = ('a'..'f').toList()
val pairs = letters.zipWithNext()
println(letters) // [a, b, c, d, e, f]
println(pairs) // [(a, b), (b, c), (c, d), (d, e), (e, f)]
but in my case letters would be:
val letters = flowOf('a'..'f')
bonus points:
i tried flowOf(1, 2, 3).scan(emptyList<Int>()) { acc, value -> acc + value }.toList() on https://play.kotlinlang.org/ but doesn't find flowOf what import or else i'm missing there?

One possible solution is:
val letters = ('a'..'f').toList().toTypedArray()
val lettersFlow = flowOf(*letters)
val result = lettersFlow.scan(Pair<Char, Char>('a','a')) { acc, value -> Pair(acc.second, value) }.drop(2).toList()
println(result)

Related

How use arrow-kt to convert a function taking two parameters into a function taking a pair?

I wrote this goofy tuplize function:
fun foo(x: Int, y: Int) = 3 * x + 2 * y + 1
fun <T, U, R> tuplize(f: (T, U) -> R): ((Pair<T, U>) -> R) = { (a, b): Pair<T, U> -> f(a, b) }
val xs = listOf(Pair(1, 2), Pair(42, 23))
val f = tuplize(::foo)
val ys = xs.map(f)
It works, but I guess arrow-kt already has something nice build-in, and I just can't find it. Can you help me out? :)
(Sure, I could just use val ys = xs.map { (a, b) -> foo(a, b) }, but in this example, the goal is to express it in point-free style.)

How to create a Mutable List of Alphabets in Kotlin?

I want to create a MutableList of alphabets form A to Z but so far I can only think of the following method as the shortest one without writing each and every alphabet.
fun main()
{
var alphabets: MutableList<Char> = mutableListOf()
for (a in 'A'..'Z')
{
alphabets.add(a)
}
print(alphabets)
}
So I wanted to know if there is any Lambda implementation or shorter method for the same?
You can use CharRange() or using .. operator to create a range.
For example:
val alphabets = ('A'..'Z').toMutableList()
print(alphabets)
// [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
or
val alphabets = CharRange('A','Z').toMutableList()
print(alphabets)
// [A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
Alternatively, you can use ('a'..'z').joinToString("").
val abc = ('a'..'z').joinToString("")
println(abc) //abcdefghijklmnopqrstuvwxyz
You can perform the same functions on a string in Kotlin as you can perform on a list of characters
For example:
for (i in abc) { println(i) }
This lists each alphabet individually on a new line just as it would if you converted it into a list.
You can use rangeTo extension function as below
private val alphabets = ('A').rangeTo('Z').toMutableList()
println(alphabets)
[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]

How to shuffle elements of Mutable list in Kotlin?

I wanted to create a MutableList of alphabets and then shuffle them and store it in another MutableList.
I used shuffle() function but it resulted in the original list being shuffled as well which I didn't wanted to happen as I will be using the original list to map it with new shuffled one.
fun main(){
val alphabets = ('A'..'Z').toMutableList()
var shuffAlp = alphabets
shuffAlp.shuffle()
println(alphabets)
println(shuffAlp)
}
So I had to create two mutable list and then shuffle one of them
val alphabets = ('A'..'Z').toMutableList()
var shuffAlp = ('A'..'Z').toMutableList()
shuffAlp.shuffle()
This might be a trivial question but is there any other way where I do not have to create two same list?
shuffle does shuffle into original list, shuffled do and return new list.
And same behavior is for sort & sorted, sortBy & sortedBy, reverse & asReversed:
fun main(){
val alphabets = ('A'..'Z').toMutableList()
val shuffAlp = alphabets.shuffled()
println(alphabets)
println(shuffAlp)
}
Result:
[A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z]
[U, B, A, N, H, R, O, K, X, C, W, E, Q, P, J, Z, L, Y, S, M, I, D, V, F, G, T]

How merge two list of objects and identify identical elements

I have 2 lists containing objects of the same type and I am looking to merge these 2 lists.
Let's take an example:
List1 contains [A, B, C, E]
List2 contains [A, D]
what I need [A, B, C, E, D]
I absolutely want the identical elements (here the object A) to be those of my list 1.
It does not matter if the order of the items is not kept.
If you want to keep identical elements from list1, you should not use distinct. Your code should be explicit on this business rule to avoid future errors.
An example :
class Elt(private val id: Int, private val content: String) {
open fun equals(other: Elt): Boolean {
return this.id == other.id
}
override fun toString(): String {
return "$id -> $content"
}
}
fun main(args: Array<String>) {
val l1 = listOf(Elt(1,"L1"), Elt(2,"L1"), Elt(3,"L1"), Elt(4,"L1"))
val l2 = listOf(Elt(1,"L2"), Elt(5,"L2"))
val l4 = l2 + l1
println(l4.distinct()) // Elt 1 comes from L2
val l5 = l1 + l2
println(l5.distinct()) // Elt 1 comes from L1
val l6 = l2.toMutableList().apply { addAll(l1) }.distinct()
println(l6.distinct()) // Elt 1 comes from L2
}
It will print:
[1 -> L1, 2 -> L1, 3 -> L1, 4 -> L1, 1 -> L2, 5 -> L2]
[1 -> L2, 5 -> L2, 1 -> L1, 2 -> L1, 3 -> L1, 4 -> L1]
[1 -> L1, 2 -> L1, 3 -> L1, 4 -> L1, 1 -> L2, 5 -> L2]
[1 -> L2, 5 -> L2, 1 -> L1, 2 -> L1, 3 -> L1, 4 -> L1]
If you remove duplicate in list2 before adding the elements, you will ensure that you keep identical ielement from list1:
val l3 = l1 + (l2 - l1.intersect(l2))
println(l3)
Simple case:
val lista = listOf( 1,2,3 )
val listb = mutableListOf( 1,4,5 ).apply { addAll(lista) }.distinct()
// result listb -> [1, 4, 5, 2, 3]
To add two string list
val a = listOf("a","b" ,"c" , "e")
val b = listOf("a", "d")
val c = a + b
To have only distinct values,
val d = c.distinct()
An alternative to the above solutions: use HashSet. Set collections don't support multiple occurrences of the same element so when you add A twice, the second one simply gets discarded.
var s: HashSet<String> = HashSet<String>()
s.addAll(listOf("A", "B", "C", "E"))
s.addAll(listOf("A", "D"))
var l = s.toList()
Since HashSet uses hashing under the hood, you get O(1) complexity on most of its operations.

How to iterate over the product of several ranges or iterators?

Is there a natural way in Rust to iterate over the "product" of several ranges or iterators?
This comes up when you're iterating over a multidimensional array, or perhaps some state space. For instance, I want to consider all possible values of a boolean tuple with 5 elements. Nesting 5 for loops is a bit unwieldy.
Here is a macro that does the job:
macro_rules! product {
($first:ident, $($next:ident),*) => (
$first.iter() $(
.flat_map(|e| std::iter::repeat(e)
.zip($next.iter()))
)*
);
}
fn main() {
let a = ['A', 'B', 'C'];
let b = [1, 4];
let c = [true, false];
let d = ['x', 'y'];
for (((a, b), c), d) in product![a, b, c, d] {
println!("{} {} {} {}", a, b, c, d);
}
}
Output:
A 1 true x
A 1 true y
A 1 false x
A 1 false y
A 4 true x
A 4 true y
etc...
Playpen example
The macro expands to the following
a.iter()
.flat_map(|e| std::iter::repeat(e).zip(b.iter()))
.flat_map(|e| std::iter::repeat(e).zip(c.iter()))
.flat_map(|e| std::iter::repeat(e).zip(d.iter()))
flat_map(|e| ... ) combines a sequence of iterators into an iterator. The e is an element yielded by an iterator.
std::iter::repeat(e) creates an iterator that repeats e.
.zip( ... ) iterates over two iterators simultaneously, yielding the elements of both as a pair.
Macros are a bit longer to explain, so it's best to read the macro chapter in the book
The itertools crate has a very ergonomic macro (iproduct!) for iterating over the product of iterators. Here is an example:
pub fn main() {
let a = ['A', 'B', 'C'];
let b = [1, 4];
let c = [true, false];
let d = ['x', 'y'];
for (a, b, c, d) in itertools::iproduct!(&a, &b, &c, &d) {
println!("{} {} {} {}", a, b, c, d);
}
}