2010-09-01 6 views
2

J'ai une longue liste de mots dans un tableau. Certains courts, d'autres longs. Je voudrais filtrer ces mots qui commencent par un mot du tableau (la longueur de ce mot "préfixe" peut être fixé, disons, à 3 caractères) et qui en même temps se termine par un mot.Comment rechercher des mots commençant et se terminant par d'autres mots du même tableau?

Disons que le premier mot est «carport». Maintenant, si 'voiture' et 'port' existent aussi dans le tableau, j'obtiendrais une correspondance. Mais si le mot est "carlsberg", je n'aurais pas de correspondance (puisque "lsberg" ne serait probablement pas un mot existant dans le tableau). Les résultats apparaîtront de préférence sous la forme "préfixe mot, suffixe mot, mot entier".

J'envisagerais d'utiliser n'importe quel langage qui peut me faire faire cela, bien que je sois moi-même surtout un type JavaScript.

+2

L'avez-vous essayé vous-même? Pouvez-vous poster ce que vous avez jusqu'ici? Merci. – alex

+0

Vous avez dit "n'importe quelle langue" - est-ce pour une application web? Si oui, quelle technologie utilisez-vous et avons-nous accès à PHP/PERL/ASP? S'il ne s'agit que d'un rechargement à la page, vous obtiendrez probablement de meilleures performances côté serveur. Si vous pouvez fournir plus d'informations, je ferai de mon mieux pour vous trouver une solution :) – Basic

+0

Ce serait une chose "exécuter une fois" pour générer un nouveau fichier. J'ai seulement essayé quelques regexp tard hier soir mais je voulais vérifier avec vous s'il y a des solutions élégantes, peu importe la langue (je sais que certaines langues sont mieux adaptées que d'autres sur différents types de tâches). Étonné par la réponse (rapide!) Jusqu'à présent, merci beaucoup! – naton

Répondre

0

Eh bien, la mise en œuvre naïve en JavaScript serait comme ceci:

function triples(words) { 
    var result = new Array(); 
    for(var i=0; i<words.length; i++) { 
     for(var j=0; j<words.length; j++) { 
      var k = words.indexOf(words[i] + words[j]); 
      if(k != -1) { 
       result.push([words[i], words[j], words[k]]); 
      } 
     } 
    } 
    return result; 
} 

La fonction sous sa forme actuelle exige que le tableau de tous les mots en tant que paramètre et retourne un tableau de tableaux contenant les triplets de mots trouvés (premier élément étant le préfixe, le deuxième élément étant le suffixe, le troisième élément étant le mot combiné).

0

Quelque chose comme ceci:

#!/usr/bin/perl 

use strict; 
use warnings; 

my @candidates=qw(carport Carsburg butterfly 
       buttercup Christmas wishlist carpface flyface buttface); 
my @arr=<DATA>; 
chomp @arr; 

for my $i (3..6) { 
    foreach my $j (@candidates) { 
     my ($fp,$lp)=($1,$2) if ($j=~/(^.{$i})(.*$)/); 
     if($fp && $lp) { 
      my @hit1=grep(/^$fp/,@arr); 
      my @hit2=grep(/$lp$/,@arr); 
      print "candidate: $j\n start= @hit1 end= @hit2\n=====\n" 
       if (scalar @hit1 && scalar @hit2); 
     } 
    } 
} 

__DATA__ 
car 
port 
wish 
list 
Christ 
mas 
butter 
cup 
fly 
face 
butt 

Sortie:

candidate: carport 
start= car end= port 
===== 
candidate: flyface 
start= fly end= face 
===== 
candidate: wishlist 
start= wish end= list 
===== 
candidate: buttface 
start= butter butt end= face 
===== 
candidate: butterfly 
start= butter end= fly 
===== 
candidate: buttercup 
start= butter end= cup 
===== 
candidate: Christmas 
start= Christ end= mas 
+0

Avoir "carport" (et d'autres mots "combinés") dans cette liste me donne "end = port carport", mais je pense que vous êtes proche de ce que je suis après. Peut-être filtrer les correspondances avec plusieurs commence et se termine? Je pense utiliser ce filtre sur une grande quantité de texte, peut-être même une sorte de dictionnaire, alors je pense que chaque mot de départ doit apparaître de toute façon? – naton

+0

Je ne suis pas sûr de comprendre. Êtes-vous en train de dire que vous avez ajouté "carport" à la liste sous "__DATA"? Si vous voulez ce type de filtrage basé sur une seule liste plutôt que deux (la façon dont je l'ai écrit), c'est une logique légèrement différente. – dawg

+0

Désolé pour réponse tardive .. Oui, une liste est ce que je vise. L'indata pourrait être un vocabulaire quelconque, pour trouver des mots composés d'autres mots de la liste. – naton

1

Je me demande si un trie aiderait, voir What is the most common use of the “trie” data structure?.

Perl dispose d'un module de couple pour les construire:

Quelque chose d'autre qui sonne un peu comme ce serait un point de départ est le module Ruby's Abbrev:

#!/usr/bin/env ruby 

require 'abbrev' 
require 'pp' 

pp %w[car port carport carlsberg].abbrev 
# >> {"por"=>"port", 
# >> "po"=>"port", 
# >> "p"=>"port", 
# >> "carpor"=>"carport", 
# >> "carpo"=>"carport", 
# >> "carp"=>"carport", 
# >> "carlsber"=>"carlsberg", 
# >> "carlsbe"=>"carlsberg", 
# >> "carlsb"=>"carlsberg", 
# >> "carls"=>"carlsberg", 
# >> "carl"=>"carlsberg", 
# >> "car"=>"car", 
# >> "port"=>"port", 
# >> "carport"=>"carport", 
# >> "carlsberg"=>"carlsberg"} 
0

Ici je sa solution Perl qui est O(n + 2m):

use warnings; 
use strict; 
use Data::Dumper; 

my @words = qw(car carport carlsberg cartographer airport photographer); 

my @ends = qw(car port air grapher); 

my $ends_re = join '|' => @ends; 

my @matches = map {/^($ends_re).*($ends_re)$/ ? [$1, $_, $2] :()} @words; 

print Dumper \@matches; 

impressions:

$VAR1 = [ 
     [ 
     'car', 
     'carport', 
     'port' 
     ], 
     [ 
     'car', 
     'cartographer', 
     'grapher' 
     ], 
     [ 
     'air', 
     'airport', 
     'port' 
     ] 
    ]; 
0

je ferais quelque chose comme:

<?php 

    $words = array('experts', 'exchange', 'expert', 'sexchange'); 

    // build trie 
    $t = array(); 
    foreach ($words as $word) 
    { 
     $n = &$t; 
     for ($i = 0; $i < strlen($word); ++$i) 
     { 
      $c = $word[$i]; 

      if (!isset($n[$c])) $n[$c] = array(); 

      $n = &$n[$c]; 
     } 

     $n['.'] = true; 
    } 

    $word = 'expertsexchange'; 

    $n = $t; 
    for ($i = 0; $i < strlen($word); ++$i) 
    { 
     $c = $word[$i]; 

     if (isset($n['.'])) 
     { 
      $o = $t; 
      for ($j = $i; $j < strlen($word); ++$j) 
      { 
       $d = $word[$j]; 
       if (!isset($o[$d])) break; 
       $o = $o[$d];      
      } 

      # found match 
      if ($j == strlen($word) && isset($o['.'])) 
      { 
       echo substr($word, 0, $i).",".substr($word,$i).",".$word."\n"; 
      } 
     } 

     if (isset($n[$c])) 
     { 
      $n = $n[$c]; 
     } 
     else 
      break; 
    } 
?> 

Results: 

expert,sexchange,expertsexchange 
experts,exchange,expertsexchange 

Je l'ai écrit sur place, donc il ne fonctionne pas tout à fait exact . Mais l'idée est de construire un arbre de préfixe et de le parcourir. Chaque fois que vous trouvez un préfixe (indiqué par un '.'), Continuez à partir du haut de l'arbre pour voir si vous pouvez trouver un suffixe à partir de ce point. Cela suppose que vous ne voulez rien entre le préfixe et le suffixe.

Questions connexes