Reputation: 8331
I have a Flowable<String>
which returns a huge list of strings with a back-pressure. Each string could be a title (group) or could be a list item. Titles starts at the beginning of line, items has preceding white-spaces e.g.:
Title-1
item-1
item-2
item-3
Title-2
item-1
item-2
Title-3
item-1
I need to split origin Flowable
to multiple Flowable
s of items based on item's title:
Flowable<String> -> Flowable<Flowable<String>>
, where first flowable has items:
[title-1.item-1, title-1.item-2, title-1.item-3]
second: [title-2.item-1, title-2.item-2]
and third: [title-3.item-1]
.
I tried to use Flowable.groupBy()
but didn't find a way to group items based on surrounding items.
Does some standard RxJava method exist to perform this operation? (of course, without loading all items in memory).
Upvotes: 0
Views: 225
Reputation: 19555
You can use Flowable.scan()
to build the next value of a flowable based on the previous build value. Use it to build the entries in the form of "titel.item"
. See the following example:
List<String> data = new ArrayList<String>();
data.add("Title-1");
data.add(" item-1");
data.add(" item-2");
data.add(" item-3");
data.add("Title-2");
data.add(" item-1");
data.add(" item-2");
data.add("Title-3");
data.add(" item-1");
Flowable<String> dataFlowable = Flowable.fromIterable(data);
Flowable<String> adjustedFlowable = dataFlowable.scan("", (a,b) -> {
if (a.equals("")) {
// it's the first loop
return b;
}
if (!b.startsWith(" ")) {
// it's a title
return b;
}
// it's a list item, so build it
String[] split = a.split("\\.", -2);
return split[0]+"."+(b.trim());
}
);
adjustedFlowable.blockingSubscribe(it -> {
System.out.println(it);
});
This will generate the following output:
Title-1
Title-1.item-1
Title-1.item-2
Title-1.item-3
Title-2
Title-2.item-1
Title-2.item-2
Title-3
Title-3.item-1
As you see the items are now enriched with the title they belong to. From there you can use any filter()
or groupBy()
you want.
Upvotes: 2
Reputation: 1001
you can use Flowable.scan()
. So you'll have something like:
originalFloawble
.scan("" to "" as Pair<String, String>) {prev, newIncome ->
if (newIncome is Title) newIncome to ""
else prev.first to newIncome
}
.filter { (title, item) -> item.isNotEmpty() }
.groupBy { it.first }
.map { it.map { (title, item) -> "$title.$item" } }
Upvotes: 0