4

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 :)

1
  • What behaviour do you expect for [product, example]? (the reverse of [example, product] Commented Apr 17, 2018 at 10:17

1 Answer 1

6

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?

Sign up to request clarification or add additional context in comments.

1 Comment

your "match" method works perfectly, thank you so much I'm gonna use this approach from now on

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.