RxJava2 how to join 2 Single List into one list - kotlin

I have 2 different data sources that I want to combine.
val source1: Single<List<Type1>> = Single.fromCallable({
api.getSource1()
})!!
val source2: Single<List<Type2>> = Single.fromCallable({
api.getSource2()
})!!
//PS.
class Type0()
class Type1 : Type0()
class Type2 : Type0()
I want to join 2 sources and get
Single<List<Type0>>
so I could do further processing of the data, I think I should use .zip method, but I am not sure how to do it correctly.

The zipWith operator works well here, as it lets you provide a BiFunction that describes how to combine the two Single instances (in this case, we just concatenate them with the plus operator):
val zipped: Single<List<Type0>> = source1.zipWith(source2, BiFunction { l1, l2 -> l1 + l2 })

Related

How to print lists in a scific order in kotlin?

im working on a project and i have a list in kotlin like:
val list = listOf("banana", "1","apple","3","banana","2")
and i want to print it like
Output:
banana = 1
banana = 2
apple = 3
so like every work with the number should be like one val, and i need to print in scific order (the order is toooo random for any sort command), so im panning on just coppying the whole xinhua dictionary here (since all chinese words have a scific unicode), and make the code it replace like:
val list = listOf("banana丨", "1","apple丩","3","banana丨","2")
but how to print them in the order?
ps. even me as a chinese dont know most of the words in xinhua dictionary lol so there is more then enofe
Assuming that you have the following input list, as shown in your question, where the order of occurrence is always one word followed by the scific order:
val list = listOf("banana", "1","apple","3","banana","2")
You could do the following:
1. Create a data class that defines one entry in your raw input list
data class WordEntry(val word: String, val order: Int)
2. Map over your raw input list by using the windowed and map methods
val dictionary = list.windowed(2, 2).map { WordEntry(it.first(), it.last().toInt()) }
Here, the windowed(2, 2) method creates a window of size 2 and step 2, meaning that we iterate over the raw input list and always work with two entries at every second step. Assuming that the order in the raw input list is always the word followed by the scific order, this should work. Otherwise, this would not work, so the order is very important here!
3. Sort the transformed dictionary by the order property
val sortedDictionary = dictionary.sortedBy { it.order }
Edit: You can also sort by any other property. Just pass another property to the lambda expression of sortedBy (e.g. sortedBy { it.word } if you want to sort it by the word property)
4. Finally, you can print out your sorted dictionary
val outputStr = sortedDictionary.joinToString("\n") { "${it.word} = ${it.order}" }
print(outputStr)
Output:
banana = 1
banana = 2
apple = 3

Combine two Flows to pairs with null values

In my application I have two Flows of data which I want to combine into a single one containing a pair of the values. However, when Flow A emits a new value the combined Flow should emit a pair with a null value until Flow B emits a new value. Think of it like this:
Flow A A --------------------------> B --------------------------> C ----->
Flow B 1 ---------> 2 ------------------------> 3 ----> 4 --------------> 5
Result A1 --------> A2 ------------> Bn ------> B3 ---> B4 ------> Cn --> C5
Where n stands for the null value. How can I create this behaviour? Is there maybe an extension function for this on Flow similar to zip or so?
I don't think there's a simple way to do this with existing flow operators, but you can roll your own by building a new flow.
fun <A, B> combineWithNulls(flowA: Flow<A>, flowB: Flow<B>) = flow {
var previousB: B? = null
combine(flowA, flowB) { a, b -> a to b }.collect { (a, b) ->
if (b == previousB) {
emit(a to null)
} else {
previousB = b
emit(a to b)
}
}
}
First we use the combine operator to create a flow that emits a new pair each time either flow emits an item. Then we collect the combined flow, and compare the value from flowB against a value that's stored in a variable our new flow. If the values match, we emit a null. Otherwise, we emit the real value and updated the stored value.

Can PICT handle independent parameters

Can PICT (=Pairwise Independent Combinatorial Testing) handle/model independent parameters.
For example in following input a and b are independent, so they should not be combined.
Input in PICT:
a: 1, 2, 3, 4
b: 5, 6, 7, 8
//some line which models the independence: a independent of b
Output, that I would expect:
a b
1 5
2 6
3 7
4 8
This example, with only 2 parameters, of course normally would not make much sense, but it's illustrative.
The same could be applied to 3 parameters (a,b,c), where a is independent of b, but not c.
The main goal of declaring parameters as independent would be the reduce the number of tests.
I read the paper/user guide to PICT, but I didn't found any useful information.
I will answer my question by myself:
The solution is to define submodels and set the default order from 2 (=pairwise) to 1 (= no combination).
For example parameter a = {a_1, a_2, a_3} should be independent of
b = {b_1, b_2, b_3} and
c = {c_1, ..., c_4}.
Therefor I would expect 12 tests ((b x c) + a).
Resulting in the following input file:
a: 1,2,3
b: 1,2,3
c: 1,2,3,4
{b,c}#2
{b,c}#2 defines a submodel, consisting of b and c, which uses pairwise combination.
And running pict with the option: "/o:1".
In PICT you can define conditions and achieve your goal to not combine them with the rest. You can add additional option as N/A and have something like this;
If [A] = '1' Then [B] = 'N/A';
This is one possible option to handle this case.

Sorting List of Objects Containing Maybe Time.Posix

I have a List of custom types that I would like to sort on one attribute which is of type Maybe Time.Posix. In reading the docs I've come to the conclusion I should use List.sortWith, as neither Maybe nor Time.Posix values are comparable. I've written a set of functions to prepare the values so they are comparable. The challenge that I'm facing, though, is pulling the values from the types in the list.
Here are the functions:
maybeCompare : (a -> a -> Order) -> Maybe a -> Maybe a -> Order
maybeCompare f a b =
case a of
Just some_a ->
case b of
Just some_b ->
f some_a some_b
Nothing ->
GT
Nothing ->
LT
posixCompare : Time.Posix -> Time.Posix -> Order
posixCompare a b = compare (posixToMillis(a)) (posixToMillis(b))
posMay = maybeCompare (posixCompare)
Which I combine and use like this:
List.sortWith (posMay .time) objList
On data that looks like this:
obj1 = {id=1,time= Just time1}
obj2 = {id=2,time= Just time2}
obj3 = {id=3,time= Just time3}
obj4 = {id=4,time= Just time4}
obj5 = {id=5,time= Nothing}
objList = obj1 :: obj2 :: obj3 :: obj4 :: obj5 :: []
Now, this approach works for a list like this List (Maybe Time.Posix). By which I mean I get the output I expect, the list is sorted on the Posix time with the Nothing values in the desired location.
However, for a List of types where Maybe Time.Posix is one of the values I get this error (one of many, but I think this is the source):
List.sortWith (posMay .time) objList
^^^^^
This .time field access function has type:
{ b | time : a } -> a
But `posMay` needs the 1st argument to be:
Maybe Time.Posix
Is there are way to make the types of my functions align to sort this kind of data? Or, should I rethink my approach?
I've created a working example at https://ellie-app.com/8dp2qD6fDzBa1
Your posMay function is of the type Maybe a -> Maybe a -> Order, so it's not expecting .time, which is a function of type {id:Int,time:Maybe Posix} -> Maybe Posix.
Instead, you can create a different function which shims between posMay and List.sortWith, which would look like this: List.sortWith (\a b -> posMay a.time b.time)
If you want to be able to pass a getter function to posMay, you could rewrite it to accept that function:
posMay getter a b =
maybeCompare posixCompare (getter a) (getter b)
Then, you would use it like this: List.sortWith (posMay .time) (or List.sortWith (posMay identity) for a List (Maybe Posix). A version that works like this is at https://ellie-app.com/8dp7gm3qthka1

Erlang's term_to_binary in Haskell?

Is there a no-fuss serialization method for Haskell, similar to Erlang's term_to_binary/binary_to_term calls? Data.Binary seems unnecessarily complicated and raw. See this example where you are basically manually encoding terms to integers.
Use Data.Binary, and one of the deriving scripts that come with the package.
It's very simple to derive Binary instances, via the 'derive' or 'deriveM' functions provided in the tools set of Data.Binay.
derive :: (Data a) => a -> String
For any 'a' in Data, it derives a Binary instance for you as a String. There's a putStr version too, deriveM.
Example:
*Main> deriveM (undefined :: Drinks)
instance Binary Main.Drinks where
put (Beer a) = putWord8 0 >> put a
put Coffee = putWord8 1
put Tea = putWord8 2
put EnergyDrink = putWord8 3
put Water = putWord8 4
put Wine = putWord8 5
put Whisky = putWord8 6
get = do
tag_ <- getWord8
case tag_ of
0 -> get >>= \a -> return (Beer a)
1 -> return Coffee
2 -> return Tea
3 -> return EnergyDrink
4 -> return Water
5 -> return Wine
6 -> return Whisky
_ -> fail "no parse"
The example you cite is an example of what the machine generated output looks like -- yes, it is all bits at the lowest level! Don't write it by hand though -- use a tool to derive it for you via reflection.