Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Kotlin find substring in list of strings

I have a string which is a product name:

val productName = "7 UP pov.a. 0,25 (24)"

and another string which is a users input in search bar, let's say:

val userInput = "up 0,25"

I'm normalizing both productName and userInput with this method:

private fun normalizeQuery(query: String): List<String> {

    val list = Normalizer.normalize(query.toLowerCase(), Normalizer.Form.NFD)
            .replace("\\p{M}".toRegex(), "")
            .split(" ")
            .toMutableList()

    for (word in list) if (word == " ") list.remove(word)

    return list

}

Now I have 2 lists of normalized strings (everything is lowercase, without empty chars, and without accented letters, e.g. Č -> c, Ž -> z, ž -> z, š -> s, ć -> c, etc.):

product = [7, up, pov.a., 0,25, (24)]
input = [up, 0,25]

Now I want (for the sake of simplicity in these examples) to return true if strings from product contains every string from input, but even as a substring, e.g.

input = [0,2, up] -> true
input = [up, 25] -> true
input = [pov, 7] -> true
input = [v.a., 4), up] -> true

Another example of wanted output:

product = [this, is, an, example, product, name]
input = [example, product] -> true
input = [mple, name] -> true
input = [this, prod] -> true

What I tried:

A) Easy and efficient way?

if (product.containsAll(input)) outputList.put(key, ActivityMain.products!![key]!!)

But this gives me what I want only if input contains EXACT same strings as in product, e.g.:

product = [this, is, an, example, product, name]
input = [example, product] -> true
input = [an, name] -> true
input = [mple, name] -> false
input = [example, name] -> true
input = [this, prod] -> false

B) Complicated way, gives me what I want, but sometimes there are unwanted results:

val wordCount = input.size
var hit = 0

for (word in input)
   for (word2 in product) 
      if (word2.contains(word))
         hit++

if (hit >= wordCount) 
    outputList.put(key, ActivityMain.products!![key]!!)

hit = 0

Help me to convert those false's into true's :)

like image 609
fkvestak Avatar asked Oct 19 '25 21:10

fkvestak


1 Answers

What about something like:

fun match(product: Array<String>, terms: Array<String>): Boolean {
    return terms.all { term -> product.any { word -> word.contains(term) } }
}

With tests:

import java.util.*

fun main(args: Array<String>) {
    val product = arrayOf("this", "is", "an", "example", "product", "name")
    val tests = mapOf(
        arrayOf("example", "product") to true,
        arrayOf("an", "name") to true,
        arrayOf("mple", "name") to true,
        arrayOf("example", "name") to true,
        arrayOf("this", "prod") to true
    )

    tests.forEach { (terms, result) ->
        System.out.println(search(product, terms) == result)
    }
}

fun match(product: Array<String>, terms: Array<String>): Boolean {
    return terms.all { term -> product.any { word -> word.contains(term) } }
}

Do you have other example/tests that doesn't work?

like image 110
Kevin Robatel Avatar answered Oct 22 '25 10:10

Kevin Robatel



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!