Rechercher plusieurs mots dans un json

Bonjour à tous,

Je cherche depuis plusieurs jours un moyen de rechercher plusieurs mots dans un fichier JSON.
Pour le moment j’arrive à rechercher 1 mot ou plusieurs, mais ils sont indépendants.
Par exemple : quand je tape « Maison » et « Voiture », il me trouve tout ce qui contient « Maison » OU « Voiture » et « Maison » ET « Voiture ». Moi je voudrais qu’il me trouve uniquement « Maison » ET « Voiture ».

J’ai essayé avec des « .filter » mais ça donne rien que je sache exploiter.
Pour le moment j’ai une boucle qui parcours mon fichier Json et qui me trouve le mot recherché, mais pas plusieurs mots en relation entre eux.

Pour le moment :

Je décompose en tableau mes mots de recherche avec une fonction du genre : searchSample.components. Qui me donne un array.
Ensuite, je peux chercher en utilisants : if variable.contains(array) { print (result) }

mais j’ai une erreur : « Cannot convert value of type ‹ [String] › to expected argument type ‹ String.Element › (aka ‹ Character ›) »

Je comprends qu’il ne peut rechercher les termes dans l’array et attend un résultat type String.

Comment faire pour faire une boucle qui recherche plusieurs mots-clefs, contenu dans un array (en supposant que je ne sais pas si l’utilisateur va recherche 1, 2, 3 mots ou plus…). Je bloque sur ce raisonnement.

Je vous remercie d’avance pour vos éventuels idées. J’ai regardé sur le net, mais j’ai rien trouvé qui correspondait à ce que je demandais. On peut bien rechercher plusieurs termes?

Pour information en PHP, j’avais trouvé une solution comme ceci :

for($i = 1; $i < count($aSearch); $i++) {
if(!empty($aSearch[$i])) {
$query .= " AND texte LIKE ‹ %" . $aSearch[$i] . "% ›";
}

Hello @Mrt1,

Peux-tu nous coller un exemple de ton fichier JSON, pour que nous puissions tester ?

Merci,
Bonne journée,

Alexandre

1 J'aime

oui j’utilise ça pour mes tests :

let testData = «  »"
[
{
« cotation »: « AAFA001 »,
« description »: « Exérèse de tumeur intraparenchymateuse du cervelet, par craniotomie »,
« tarif1 »: « 594,89 »
},
{
« cotation »: « AAFA002 »,
« description »: « Exérèse de tumeur intraparenchymateuse du cerveau, par craniotomie »,
« tarif1 »: « 525,51 »
},
{
« cotation »: « AAFA003 »,
« description »: « Exérèse de lésion du tronc cérébral, par craniotomie »,
« tarif1 »: « 813,14 »
},
{
« cotation »: « AAFA004 »,
« description »: « Hémisphérectomie fonctionnelle, par craniotomie »,
« tarif1 »: « 850,16 »
},
{
« cotation »: « AAFA005 »,
« description »: « Exérèse de lésion du corps calleux, du fornix hypothalamique ou du septum pellucide, par craniotomie »,
« tarif1 »: « 655,65 »
},
{
« cotation »: « AAFA006 »,
« description »: « Résection de parenchyme cérébral pour infarctus expansif, par craniotomie »,
« tarif1 »: « 418 »
},
{
« cotation »: « AAFA007 »,
« description »: « Excision d’une zone épileptogène, par craniotomie »,
« tarif1 »: « 524,28 »
},
{
« cotation »: « AAFA008 »,
« description »: « Résection de parenchyme cérébelleux pour infarctus expansif, par craniotomie »,
« tarif1 »: « 418 »
},
{
« cotation »: « AAGA900 »,
« description »: « Ablation d’électrode corticale cérébrale, par craniotomie »,
« tarif1 »: « Non pris en charge »
},
{
« cotation »: « AAGB001 »,
« description »: « Ablation d’électrode intracérébrale »,
« tarif1 »: « 93,63 »
}
]
«  »".data(using: .utf8)

Merci d’avance !

Là comme ça je peux te répondre tout de suite, il n’y a pas de « camion », ni de « maison » dans ta base de données !

Oui, je flood !

Question : est-ce ton critère de recherche a besoin nécessairement de deux mots, ou est-ce variable, de 1 à n clés ?

2 J'aimes

Merci pour vos réponses.

C’est variable, de 1 à n clés.
En fait, je m’entraine pour rechercher dans la CCAM (actes médicaux de l’assurance maladie), et j’aimerai que l’on puisse rechercher avec plusieurs mots-clefs.
J’ai, en exemple, ce que j’avais fait pour le web : http://laforgedentaire.net/ccam/
C’est pas parfait, mais en php j’avais trouvé le truc (je l’ai publié dans mon premier post).

J’aimerai refaire tout ça (en mieux) en Swift. J’avoue que je bloque sur ce raisonnement de plusieurs mots-clefs dans ma recherche dans mon fichier JSON dans ce langage. J’y arrive pour 1 mot uniquement pour le moment. Mais pas plusieurs et surtout en relation entre eux.

Taper à l’arrache, juste pour vérifier que cela fonctionne :

import SwiftUI

class Test : ObservableObject {
  
  func unTest() -> String {
    let liste = [
      "maison voiture hiboux genoux",
      "hiboux piscine voiture",
      "passe-moi le truc"]
    
    let cle1 = "voiture"
    let cle2 = "piscine"
    
    for  suspect in liste {
      if suspect.contains(cle1) &&
          suspect.contains(cle2) {
        return suspect
      }
    }
    
    return "Pas de coupable !"
    
  }
}


struct ContentView: View {
  @ObservedObject var recherche = Test()
  
    var body: some View {
      VStack {
        Text(recherche.unTest())
      }
    }
}
1 J'aime

Merci Draken.

J’étais arrivé aussi à ce résultat.
Par contre, je n’arrive pas à réaliser un résultat similaire si :
1 - Je ne connais pas le nombre de clé à la base.
La on définit clairement clé1 et clé2, mais si l’input de recherche en contient 3 ou 2 ou 6?
2 - Dans la boucle avec « suspect.contains », le raisonnement est le même. Comment mettre dans le code le même raisonnement avec un nombre de « n » clé ? On passe par une boucle ? Je pensais utiliser un « .filter » mais je n’y suis pas arrivé. En gros un truc genre « suspect.contains(clé 1)…suspect.contains(clé n).

Un grand merci pour ton aide.

EDIT : Sinon je pensais éventuellement faire une première recherche avec un mot-clé, l’enregistré dans une liste, puis refaire une recherche avec le 2ème mot clef dans cette nouvelle liste… mais je trouve la solution alambiquée.

EDIT 2 : J’ai testé cette fonction qui fonctionne :
func inArray(_ a1: [String], _ a2: [String]) -> [String] {
return a1.filter({ (str) in
a2.contains(where: { $0.contains(str) })
})
}
let x = inArray([« ab », « cd », « ef »], [« xyzabpqr », « qwerty », « acdfg »])
print(x) //[« cd », « ab »]

C’est ce que je voudrais faire exactement. Par contre, avec le JSON, j’ai un format Data et il n’accepte pas avec l’erreur « Cannot convert value of type ‹ [String] › to expected argument type ‹ String.Element › (aka ‹ Character ›) »

La conversion en utilisant un
let str = String(decoding: data, as: UTF8.self)

Ne fonctionne pas et me retourne cette erreur : « Type of expression is ambiguous without more context »

Bref, je tourne en rond…

Désolé, cela sort de mon domaine de compétence. Je n’ai jamais utilisé de JSON.


J’allais te proposer une variante de mon test (avec une boucle supplémentaire pour parcourir un tableau des clés de taille quelconque, mais ce n’est plus la peine).

1 J'aime

Merci pour la tentative !
Je vais continuer de chercher une solution.

Bonne journée :slight_smile: