3 votes

Kotlin trouve la sous-chaîne dans une liste de chaînes de caractères

J'ai une chaîne de caractères qui est un nom de produit :

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

et une autre chaîne qui est une entrée des utilisateurs dans la barre de recherche, disons :

val userInput = "up 0,25"

Je normalise à la fois productName et userInput avec cette méthode :

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

}

J'ai maintenant 2 listes de chaînes de caractères normalisées (tout est en minuscules, sans caractères vides, et sans lettres accentuées, par exemple Č -> c, Ž -> z, ž -> z, š -> s, ć -> c, etc :)

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

Maintenant, je veux (pour des raisons de simplicité dans ces exemples) renvoyer true si les chaînes du produit contiennent chaque de l'entrée, mais même en tant que sous-chaîne par exemple

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

Un autre exemple de sortie souhaitée :

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

Ce que j'ai essayé :

A) Un moyen simple et efficace ?

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

Mais cela me donne ce que je veux seulement si l'entrée contient EXACTEMENT les mêmes chaînes que dans le produit, par exemple :

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) Méthode compliquée, qui me donne ce que je veux, mais qui donne parfois des résultats non désirés :

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

Aidez-moi à convertir ces faux en vrais :)

2voto

Kevinrob Points 416

Et quelque chose comme :

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

Avec des 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) } }
}

Avez-vous d'autres exemples/tests qui ne fonctionnent pas ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X