Why distinctUntilChanged() in RxJava2 prevent data with different hashCode? - rx-java2

I used distinctUntilChanged() to filter duplicate emittions in Observable.
But it filtered different emitted data. I used map() function before and after distinctUntilChanged() as below, and I found out just the before one printed logs.
..
...
.map(t -> {
Timber.d("hashcode: %d", t.hashCode());
return t;
})
.distinctUntilChanged()
.map(t -> {
Timber.d("hashcode2: %d", t.hashCode());
return t;
})
.replay(1)
.autoConnect(0);
printed logs:
hashcode: -1015116098
hashcode: -981267991
Why did not print any log with "hashcode2"?

In according to #akarnokd 's comment,
You have a mutable datastructure of which you manipulate previous items or you send only one reference over and over thus it is always equal to itself
He said correct t is a mutable class that keeps some fields and a List.
I changed an item of the "list" inside a foreach. In fact my mistake was there :(, finally, I replaced foreach loop with an indexed loop and my problem solved.
Some Q&A about loop

Related

Are lists ensured to be processed in order by a for loop?

In a Flutter application, is the order of a list always ensured?
List<MyClass> myObjects;
// ... many add operations
int i = 0;
for(MyClass myObject in myObjects) {
assert(myObject == myObjects[i]); // will it always go through?
i++;
}
If not, what is the most efficient way to ensure a list is maintained and processed in the right order?
Yes. for-in in Dart works on Iterable objects. (It is not like for-in in JavaScript which iterates over object properties, which could be in some indeterminate order.)
From the List documentation:
Lists are Iterable. Iteration occurs over values in index order.

How to map over an array, use an if clause, and filter out the bad data?

I have an array of words, some may or may not have typos.
potentialWords = ["hello", "lkasjdf", "hunry"]
What I want to do is, return an array of all valid words, and also those words that were able to be autocorrected using a function I created correctWord. It returns an array of potential matches. so "hunry" might return ["hungry", "hurry"]. I will select the first index for the best guess.
Some words cannot be corrected however! e.g. "lkasjdf" will not find any corrections, but "hunry" will.
I was trying something like:
potentialWords.map {
if correctWord($0) != nil {
return correctWord($0)[0]
}
}
of course this will complain and say that I need a return outside the if clause. I can filter the list based on if the word can be corrected, and then map over the filtered list, re-checking which words need to be corrected, but this runs the correctWord function way too many times, and it is very sensitive.
I would like to be able to do one single pass through, and return an array of all valid words, and also corrected words.
P.S. I am calling correctWord twice in the map function for brevity, but of course I would assign correctWord($0) to a variable, and then if it isn't nil, take the first index and add it to the new list.
I think you're after flatMap. It's the same as map except it will also filter out any nil values.
potentialWords.flatMap { correctWord($0)?.first }

Array of observables where the output of each is the input of the next

I'm trying to use RxSwift to execute actions on multiple data sources. However, I have no idea how to accomplish the following.
I have an array of observabless where the output of each, should be the input of the next. So, I want to do something like, get the first observable, wait for the result and pass it to the next, all the way to the end of the array and return one final value.
Is that possible? Thanks in advance.
*** Update: Ok, I'll be more specific as requested.
The 'observables' I'm using in the array, are custom. I use a function that returns Observable.create { ... }. Inside the closure, I run an asynchronous operation that transforms the value and then send the result to the observer before completing. That resulting value, must pass to the next observable, and so on to the last observable in the array to get a final value.
The observables may send multiple values, but they must pass from one observable to the next like an assembly line.
It is difficult to know exactly what you are asking for, since Observables do not exactly have inputs but I think this is a common problem.
You may be looking for a combination of the concat or reduce operators, which allow you to accumulate data from the values emitted from an Observable. See ReactiveX's documentation for Mathematical and Aggregate Operators.
Hopefully this can get you started:
// "I have an array of observables..."
let one = Observable.deferred { Observable.just(1) }
let two = Observable.deferred { Observable.just(2) }
let observables = [one, two]
// "the output of each, should be the input of the next"
// this is problematic, because observables do not strictly have inputs.
let resultsFromEach = Observable.concat(observables)
resultsFromEach
.reduce(0) { result, next in
result + 1
}
.debug("result")
.subscribe()

Are there any side effects of exiting a loop with return rather than break in Swift?

I need to match items in two different arrays (one with imported items and another with local items that share some properties with the imported items) to sync two databases that are quite different. I need to use several criteria to do the matching to increase the robustness of finding the right local item and match it with the imported item. I could check each criterium in the same loop, but that is too expensive, because the criteria are checked by the likelihood of success in descending order. Thus, in my first implementation I used a boolean flag called found to flag that the checking of other criteria should be ignored.
Using pseudo code:
// calling code for the matching
for item in importedItems {
item.match() }
In the imported item class:
match()
{
var found = false
for localItem in localItems
{
if (self.property == localItem.property)
{
// update the local item here
found = true
break
}
}
// match with less likely 2nd property
if (!found)
{
for localItem in localItems
{
if (self.property2 == localItem.property2)
{
// update the local item here
found = true
break
}
}
}
The if !found {...} pattern is repeated two additional times with even less likely criteria.
After reviewing this code, it is clear that this can be optimized by returning instead of breaking when there is a match.
So, my question is "are there any known side-effects of leaving a loop early by using return instead of break in Swift?" I could not find any definitive answer here in SO or in the Swift documentation or in blogs that discuss Swift flow control.
No, there are no side effects, quite the opposite it's more efficient.
It's like Short-circuit evaluation in a boolean expression.
But your code is a bad example because found cannot be used outside the function.
This is a more practical example returning a boolean value
func match() -> Bool
{
for localItem in localItems
{
if (self.property == localItem.property)
{
// update the local item here
return true
}
}
....
return false
}
If you know for sure that you can return because nothing else have to be done after the loop then there are no side effects of using return

how do I use StartWith() rx operator but only if sequence is not empty?

I have a rx observable and I need to add one certain item but only if observable emit at least one item.
I went trough all the operators but couldn't find appropriate. The closest is StartWith but according to diagram it emits item immediately and does not take in count next items.
Is it possible to achieve this by combining it with some other operators ?
Thanks.
I have been trying to do the same and the only thing I came up with is not very reactive:
Observable.just(1, 2, 3)
.toList()
.flatMap(items -> {
if (items.size() > 0) {
items.add(0, 0);
}
return Observable.from(items);
})
It's far from perfect and will not work in case of "hot" observable.