title: Android Paging 3 how to filter, sort and search my data
body: <p>I'm trying to implement paging I'm using Room and it took me ages to realize that its all done for me  but what I need to do is be able to filter search and sort my data. I want to keep it as LiveData for now I can swap to flow later.
  I had this method to filter search and sort and it worked perfectly,</p>
  <pre><code>    @SuppressLint(&quot;DefaultLocale&quot;)
      private fun searchAndFilterPokemon(): LiveData&lt;List&lt;PokemonWithTypesAndSpecies&gt;&gt; {
          return Transformations.switchMap(search) { search -&gt;
              val allPokemon = repository.searchPokemonWithTypesAndSpecies(search)
              Transformations.switchMap(filters) { filters -&gt;
                  val pokemon = when {
                      filters.isNullOrEmpty() -&gt; allPokemon
                      else -&gt; {
                          Transformations.switchMap(allPokemon) { pokemonList -&gt;
                              val filteredList = pokemonList.filter { pokemon -&gt;
                                  pokemon.matches = 0
                                  val filter = filterTypes(pokemon, filters)
                                  filter
                              }
                              maybeSortList(filters, filteredList)
                          }
                      }
                  }
                  pokemon
              }
          }
      }
  </code></pre>
  <p>It have a few switchmaps here, the first is responding to search updating</p>
  <pre><code>    var search: MutableLiveData&lt;String&gt; = getSearchState()
  </code></pre>
  <p>the second is responding to filters updating</p>
  <pre><code>    val filters: MutableLiveData&lt;MutableSet&lt;String&gt;&gt; = getCurrentFiltersState()
  </code></pre>
  <p>and the third is watching the searched list updating, it then calls filterTypes and maybeSortList which are small methods for filtering and sorting</p>
  <pre><code>    @SuppressLint(&quot;DefaultLocale&quot;)
      private fun filterTypes(
          pokemon: PokemonWithTypesAndSpecies,
          filters: MutableSet&lt;String&gt;
      ): Boolean {
          var match = false
          for (filter in filters) {
              for (type in pokemon.types) {
                  if (type.name.toLowerCase() == filter.toLowerCase()) {
                      val matches = pokemon.matches.plus(1)
                      pokemon.apply {
                          this.matches = matches
                      }
                      match = true
                  }
              }
          }
          return match
      }
  
      private fun maybeSortList(
          filters: MutableSet&lt;String&gt;,
          filteredList: List&lt;PokemonWithTypesAndSpecies&gt;
      ): MutableLiveData&lt;List&lt;PokemonWithTypesAndSpecies&gt;&gt; {
          return if (filters.size &gt; 1)
              MutableLiveData(filteredList.sortedByDescending {
                  Log.d(&quot;VM&quot;, &quot;SORTING ${it.pokemon.name} ${it.matches}&quot;)
                  it.matches
              })
          else MutableLiveData(filteredList)
      }
  </code></pre>
  <p>as mentioned I want to migrate these to paging 3 and am having difficulty doing it Ive changed my repository and dao to return a PagingSource and I just want to change my view model to return the PagingData as a live data, so far I have this</p>
  <pre><code>@SuppressLint(&quot;DefaultLocale&quot;)
  private fun searchAndFilterPokemonPager(): LiveData&lt;PagingData&lt;PokemonWithTypesAndSpecies&gt;&gt; {
      val pager =  Pager(
          config = PagingConfig(
              pageSize = 50,
              enablePlaceholders = false,
              maxSize = 200
          )
      ){
          searchAndFilterPokemonWithPaging()
      }.liveData.cachedIn(viewModelScope)
  
      Transformations.switchMap(filters){
          MutableLiveData&lt;String&gt;()
      }
  
      return Transformations.switchMap(search) {search -&gt;
          val searchedPokemon =
              MutableLiveData&lt;PagingData&lt;PokemonWithTypesAndSpecies&gt;&gt;(pager.value?.filter { it.pokemon.name.contains(search) })
          Transformations.switchMap(filters) { filters -&gt;
              val pokemon = when {
                  filters.isNullOrEmpty() -&gt; searchedPokemon
                  else -&gt; {
                      Transformations.switchMap(searchedPokemon) { pokemonList -&gt;
                          val filteredList = pokemonList.filter { pokemon -&gt;
                              pokemon.matches = 0
                              val filter = filterTypes(pokemon, filters)
                              filter
                          }
                          maybeSortList(filters, filteredList = filteredList)
                      }
                  }
              }
              pokemon
          }
      }
  }
  </code></pre>
  <p>but the switchmap is giving me an error that</p>
  <pre><code>Type inference failed: Cannot infer type parameter Y in 
  
  fun &lt;X : Any!, Y : Any!&gt; switchMap
  (
      source: LiveData&lt;X!&gt;,
      switchMapFunction: (input: X!) → LiveData&lt;Y!&gt;!
   )
  </code></pre>
  <p>which I think I understand but am not sure how to fix it, also the filter and sort methods won't work anymore and I cant see any good method replacements for it with the PageData, it has a filter but not a sort? any help appreciated
  : LiveData&lt;Y!</p>
  <p><strong>UPDATE</strong> thanks to @Shadow I've rewritten it to implement searching using a mediator live data but im still stuck on filtering</p>
  <pre><code>    init {
          val combinedValues =
              MediatorLiveData&lt;Pair&lt;String?, MutableSet&lt;String&gt;?&gt;?&gt;().apply {
                  addSource(search) {
                      value = Pair(it, filters.value)
                  }
                  addSource(filters) {
                      value = Pair(search.value, it)
                  }
              }
  
          searchPokemon = Transformations.switchMap(combinedValues) { pair -&gt;
              val search = pair?.first
              val filters = pair?.second
              if (search != null &amp;&amp; filters != null) {
                  searchAndFilterPokemonPager(search)
              } else null
          }
      }
  
  
  
      @SuppressLint(&quot;DefaultLocale&quot;)
      private fun searchAndFilterPokemonPager(search: String): LiveData&lt;PagingData&lt;PokemonWithTypesAndSpecies&gt;&gt; {
          return Pager(
              config = PagingConfig(
                  pageSize = 50,
                  enablePlaceholders = false,
                  maxSize = 200
              )
          ){
              searchAllPokemonWithPaging(search)
          }.liveData.cachedIn(viewModelScope)
  
      }
  
      @SuppressLint(&quot;DefaultLocale&quot;)
      private fun searchAllPokemonWithPaging(search: String): PagingSource&lt;Int, PokemonWithTypesAndSpecies&gt; {
          return repository.searchPokemonWithTypesAndSpeciesWithPaging(search)
      }
  </code></pre>