2009-09-29 14 views
0

j'ai une liste de mots dans lesquels certains sont composés mots, dans l'exemplemots Supprimer composé

  • Palanca
  • plato
  • platopalanca

Je dois enlever "plato" et "palanca" et laissez seulement "platopalanca". Utilisé array_unique pour supprimer les doublons, mais ces mots composés sont difficiles ...

Dois-je trier la liste par longueur de mot et comparer un par un? Une expression régulière est la réponse?

mise à jour: La liste des mots est beaucoup plus grand et mélangé, non seulement des mots liés

mise à jour 2: Je peux en toute sécurité imploser le tableau dans une chaîne.

mise à jour 3: J'essaie d'éviter de faire comme si c'était un genre de pompon. il doit y avoir un moyen plus efficace de le faire

Eh bien, je pense qu'un Buble-genre comme approche est la seule possible :-( Je ne l'aime pas, mais il est ce que j'ai ... toute meilleure approche

function sortByLengthDesc($a,$b){ 
return strlen($a)-strlen($b); 
} 

usort($words,'sortByLengthDesc'); 
$count = count($words); 
for($i=0;$i<=$count;$i++) { 
    for($j=$i+1;$j<$count;$j++) { 
     if(strstr($words[$j], $words[$i])){ 
      $delete[]=$i; 
     } 
    } 
} 
foreach($delete as $i) { 
    unset($words[$i]); 
} 

mise à jour 5:... Désolé je suis un crétin Jonathan Swift me faire comprendre que je pose la mauvaise question Étant donné x mots qui commencent même, je dois retirer les shortests

  • "chaud, chien, stand, hotdo gstand "devrait devenir "chien, stand, hotdogstand"
  • "voiture, animal de compagnie, tapis" devrait devenir "animal de compagnie, tapis"
  • "Palanca, Plato, platopalanca" devrait devenir "Palanca, platopalanca"
  • " platoother , autre "devrait être intouchée, ils commencent tous les deux différents
+0

Donc un mot est un mot composé si ses composants sont aussi dans la liste? Qu'en est-il de * voiture *, * animal * et * tapis *? – Gumbo

+0

OUI. il y a des noms de parties, donc je n'ai pas ce problème de "tapis" :-) –

+0

Il est possible d'avoir des entrées comme "platoother" où "other" n'est pas dans le tableau, et si oui quelle action prendriez-vous ? – Neel

Répondre

2

Je pense que vous devez définir le problème un peu plus , afin que nous puissions donner une réponse solide. Voici quelques listes pathologiques. Quels éléments doivent être supprimés ?:

  • chaud, chien, hotdogstand.
  • chaud, chien, stand, hotdogstand
  • chaud, chiens, stand, hotdogstand

CERTAINS CODE

Ce code devrait être plus efficace que celui que vous avez:

$words = array('hatstand','hat','stand','hot','dog','cat','hotdogstand','catbasket'); 

$count = count($words); 

for ($i=0; $i<=$count; $i++) { 
    if (isset($words[$i])) { 
     $len_i = strlen($words[$i]); 
     for ($j=$i+1; $j<$count; $j++) { 
      if (isset($words[$j])) { 
       $len_j = strlen($words[$j]); 

       if ($len_i<=$len_j) { 
        if (substr($words[$j],0,$len_i)==$words[$i]) { 
         unset($words[$i]); 
        } 
       } else { 
        if (substr($words[$i],0,$len_j)==$words[$j]) { 
         unset($words[$j]); 
        } 
       } 
      } 
     } 
    } 
} 

foreach ($words as $word) { 
    echo "$word<br>"; 
} 

Vous pouvez optimiser cela en stockant des longueurs de mots dans un tableau avant les boucles.

+0

J'ai déjà pris en charge des formes plurielles. Je suis en train de mettre à jour ma question. Vous me faites réaliser que je prenais la mauvaise approche +1. –

0

Vous pouvez prendre chaque mot et voir, si un mot de tableau commence avec elle ou se termine avec elle. Si oui, ce mot doit être supprimé (unset()).

0

Regex pourrait fonctionner. Vous pouvez définir dans la regex où le début et la fin de la chaîne s'applique.

^définit le début $ définit la fin

donc quelque chose comme

foreach($array as $value) 
{ 
    //$term is the value that you want to remove 
    if(preg_match('/^' . $term . '$/', $value)) 
    { 
     //Here you can be confident that $term is $value, and then either remove it from 
     //$array, or you can add all not-matched values to a new result array 
    } 
} 

éviterait votre problème

Mais si vous êtes en train de vérifier que deux valeurs sont égales, == sera fonctionne aussi bien que (et peut-être plus rapidement que) preg_match

Si la liste des termes $ et $ values ​​est énorme Ce ne sera pas la stratégie la plus efficace, mais c'est une solution simple.Si la performance est un problème, le tri (notez la fonction sort fournie) des listes, puis l'itération des listes côte à côte pourrait être plus utile. Je vais tester cette idée avant de poster le code ici.

0

Vous pouvez placer les mots dans un tableau, trier le tableau par ordre alphabétique, puis le parcourir en boucle en vérifiant si les mots suivants commencent par l'index en cours, ce qui en fait des mots composés. Si oui, vous pouvez supprimer le mot dans l'index actuel et les dernières parties des mots suivants ...

Quelque chose comme ceci:

$array = array('palanca', 'plato', 'platopalanca'); 
// ok, the example array is already sorted alphabetically, but anyway... 
sort($array); 

// another array for words to be removed 
$removearray = array(); 

// loop through the array, the last index won't have to be checked 
for ($i = 0; $i < count($array) - 1; $i++) { 

    $current = $array[$i]; 

    // use another loop in case there are more than one combined words 
    // if the words are case sensitive, use strpos() instead to compare 
    while ($i < count($array) && stripos($array[$i + 1], $current) === 0) { 
    // the next word starts with the current one, so remove current 
    $removearray[] = $current; 
    // get the other word to remove 
    $removearray[] = substr($next, strlen($current)); 
    $i++; 
    } 

} 

// now just get rid of the words to be removed 
// for example by joining the arrays and getting the unique words 
$result = array_unique(array_merge($array, $removearray)); 
+0

Pourquoi la downvote? – kkyy

Questions connexes