2011-09-23 4 views
6

Sto cercando una funzione javascript che sia abbastanza intelligente da rimuovere l'ultima frase di una lunga porzione di testo (un paragrafo in realtà). Un testo di esempio per mostrare la complessità:Javascript (jQuery) rimuove l'ultima frase del testo lungo

<p>Blabla, some more text here. Sometimes <span>basic</span> html code is used but that should not make the "selection" of the sentence any harder! I looked up the window and I saw a plane flying over. I asked the first thing that came to mind: "What is it doing up there?" She did not know, "I think we should move past the fence!", she quickly said. He later described it as: "Something insane."</p> 

Ora ho potuto dividere il . e rimuovere l'ultima voce della matrice, ma che non avrebbe funzionato per le frasi che terminano con ? o ! e alcune frasi terminare con citazioni come something: "stuff."

function removeLastSentence(text) { 
    sWithoutLastSentence = ...; // ?? 
    return sWithoutLastSentence; 
} 

Come fare? Cos'è un algoritmo corretto?

Modifica - Con testo lungo intendo tutto il contenuto di mia paragrafo e dalla frase intendo una frase reale (non una linea), quindi nel mio esempio l'ultima frase è: He later described it as: "Something insane." quando quella viene rimosso, il il prossimo è She did not know, "I think we should move past the fence!", she quickly said."

+0

Definire "ultima frase" e "stringa lunga". Se stai cercando un metodo per limitare il numero di righe in un testo, consulta ** [questa risposta] (http://stackoverflow.com/questions/7519337/given-a-textarea-is-there-a- modo da limitare la lunghezza a base-su-di-linee/7521855 # 7521855) **. –

+0

Modificata la mia domanda, per frase intendo una frase reale, vedi sopra. :) – bartolsthoorn

+0

*** Più tardi lo descrisse come: "Qualcosa di folle". *** Io non sono un inglese maggiore .. ma è corretto? o dovrebbe essere *** Più tardi lo descrisse come "Qualcosa di pazzo". – rlemon

risposta

2

Definire le regole: [.!?] // 1. Una frase inizia con la lettera maiuscola // 2. Una frase è preceduta da nulla, o, ma non [,:;] // 3. Una frase può essere preceduta da virgolette se non formattata correttamente, come ["'] // 4. In questo caso, una frase potrebbe non essere corretta se la parola che segue una citazione è un Nome

di eventuali norme supplementari

Definire il vostro scopo:? // 1. Rimuovere l'ultima frase

Ipotesi: Se hai iniziato dall'ultimo carattere della stringa di testo e lavorato a ritroso, allora si sarebbe identificare l'inizio della frase come: 1. La stringa di testo prima del carattere è [.?!] OR 2. La stringa di testo prima del carattere è ["'] e preceduta da una lettera maiuscola 3. Ogni [.] È preceduto da uno spazio 4. Non stiamo correggendo i tag html 5. Queste ipotesi non sono solide e dovranno essere adattate regolarmente

Soluzione possibile: Leggere nella stringa e dividerlo sul carattere dello spazio per fornirci blocchi di stringhe da rivedere al contrario.

var characterGroups = $('#this-paragraph').html().split(' ').reverse(); 

Se la stringa è:

Blabla, un po 'di testo qui. A volte viene usato un codice html di base, ma questo non dovrebbe rendere più difficile la "selezione" della frase! Alzai lo sguardo verso la finestra e vidi un aereo che sorvolava. Ho chiesto la prima cosa che mi è venuta in mente: "Cosa sta facendo lassù?" Non sapeva, "Penso che dovremmo oltrepassare il recinto!", Disse rapidamente. Più tardi lo descrisse come: "Qualcosa di folle."

var originalString = 'Blabla, some more text here. Sometimes <span>basic</span> html code is used but that should not make the "selection" of the sentence any harder! I looked up the window and I saw a plane flying over. I asked the first thing that came to mind: "What is it doing up there?" She did not know, "I think we should move past the fence!", she quickly said. He later described it as: "Something insane."'; 

Poi l'array in characterGroups sarebbe:

["insane."", ""Something", "as:", "it", "described", "later", "He", 
"said.", "quickly", "she", "fence!",", "the", "past", "move", "should", "we", 
"think", ""I", "know,", "not", "did", "She", "there?"", "up", "doing", "it", 
"is", ""What", "mind:", "to", "came", "that", "thing", "first", "the", "asked", 
"I", "over.", "flying", "plane", "a", "saw", "I", "and", "window", "the", "up", 
"looked", "I", "harder!", "any", "sentence", "the", "of", ""selection"", "the", 
"make", "not", "should", "that", "but", "used", "is", "code", "html", "basic", 
"Sometimes", "here.", "text", "more", "some", "Blabla,"] 

Nota:dei '' tag e gli altri sarebbe stato rimosso utilizzando il metodo .text() in jQuery

Ogni blocco è seguito da uno spazio, quindi quando abbiamo identificato la posizione iniziale della frase (per indice di matrice) sapremo quale indice ha lo spazio e possiamo dividere la stringa originale nel ocation dove lo spazio occupa quell'indice dalla fine della frase.

darci una variabile per marcare se abbiamo trovato o meno e una variabile per contenere la posizione di indice dell'elemento dell'array identifichiamo come tenere l'inizio dell'ultima frase:

var found = false; 
var index = null; 

Loop attraverso l'array e cercare qualsiasi elemento che termina in [.!?] o terminano in "dove l'elemento precedente è iniziato con una lettera maiuscola.

var position  = 1,//skip the first one since we know that's the end anyway 
    elements  = characterGroups.length, 
    element  = null, 
    prevHadUpper = false, 
    last   = null; 

while(!found && position < elements) { 
    element = characterGroups[position].split(''); 

    if(element.length > 0) { 
     last = element[element.length-1]; 

     // test last character rule 
     if(
      last=='.'      // ends in '.' 
      || last=='!'     // ends in '!' 
      || last=='?'     // ends in '?' 
      || (last=='"' && prevHadUpper) // ends in '"' and previous started [A-Z] 
     ) { 
      found = true; 
      index = position-1; 
      lookFor = last+' '+characterGroups[position-1]; 
     } else { 
      if(element[0] == element[0].toUpperCase()) { 
      prevHadUpper = true; 
      } else { 
      prevHadUpper = false; 
      } 
     } 
    } else { 
     prevHadUpper = false; 
    } 
    position++; 
} 

Se si esegue lo script di cui sopra sarà di identificare correttamente 'e' come il inizio dell'ultima frase:

console.log(characterGroups[index]); // He at index=6 

Ora è possibile eseguire attraverso la stringa che si aveva prima:

var trimPosition = originalString.lastIndexOf(lookFor)+1; 
var updatedString = originalString.substr(0,trimPosition); 
console.log(updatedString); 

// Blabla, some more text here. Sometimes <span>basic</span> html code is used but that should not make the "selection" of the sentence any harder! I looked up the window and I saw a plane flying over. I asked the first thing that came to mind: "What is it doing up there?" She did not know, "I think we should move past the fence!", she quickly said. 

eseguire di nuovo e ottenere: Blabla, un po 'di testo qui. A volte viene usato un codice html di base, ma questo non dovrebbe rendere più difficile la "selezione" della frase! Alzai lo sguardo verso la finestra e vidi un aereo che sorvolava. Ho chiesto la prima cosa che mi è venuta in mente: "Cosa sta facendo lassù?"

Eseguire di nuovo e ottenere: Blabla, un po 'più di testo qui. A volte viene usato un codice html di base, ma questo non dovrebbe rendere più difficile la "selezione" della frase! Alzai lo sguardo verso la finestra e vidi un aereo che sorvolava.

Eseguire di nuovo e ottenere: Blabla, un po 'più di testo qui. A volte viene usato un codice html di base, ma questo non dovrebbe rendere più difficile la "selezione" della frase!

Eseguire di nuovo e ottenere: Blabla, un po 'più di testo qui.

Eseguire di nuovo e ottenere: Blabla, un po 'più di testo qui.

Quindi, I penso che corrisponda a quello che stai cercando?

In funzione:

function trimSentence(string){ 
    var found = false; 
    var index = null; 

    var characterGroups = string.split(' ').reverse(); 

    var position  = 1,//skip the first one since we know that's the end anyway 
     elements  = characterGroups.length, 
     element  = null, 
     prevHadUpper = false, 
     last   = null, 
     lookFor  = ''; 

    while(!found && position < elements) { 
     element = characterGroups[position].split(''); 

     if(element.length > 0) { 
      last = element[element.length-1]; 

      // test last character rule 
      if(
       last=='.' ||    // ends in '.' 
       last=='!' ||    // ends in '!' 
       last=='?' ||    // ends in '?' 
       (last=='"' && prevHadUpper) // ends in '"' and previous started [A-Z] 
      ) { 
       found = true; 
       index = position-1; 
       lookFor = last+' '+characterGroups[position-1]; 
      } else { 
       if(element[0] == element[0].toUpperCase()) { 
       prevHadUpper = true; 
       } else { 
       prevHadUpper = false; 
       } 
      } 
     } else { 
      prevHadUpper = false; 
     } 
     position++; 
    } 


    var trimPosition = string.lastIndexOf(lookFor)+1; 
    return string.substr(0,trimPosition); 
} 

E 'banale per fare un plugin per se, ma attenzione le ipotesi! :)

Questo aiuto?

Grazie, AE

0

Questo è buono. Perché non crei una variabile temporanea, converti tutto '!' e '?' in ".", dividi quella variabile temporanea, rimuovi l'ultima frase, unisci quella matrice temporanea in una stringa e prendi la sua lunghezza? Poi sottostringa il paragrafo originale fino a quel lunghezza

+0

O hey, usa solo Regex ed è più facile di una tonnellata = P – EHorodyski

+0

In realtà sostituendo '." 'Alla fine di una frase potrei farla franca solo con' /[\.!?]/ ', la regexp che @omnosis menzionato – bartolsthoorn

+0

Ti imbatterai ancora in un problema con frasi che contengono citazioni con punteggiatura finale, come nel tuo esempio. – samiz

1

Questo dovrebbe farlo.

/* 
Assumptions: 
- Sentence separators are a combination of terminators (.!?) + doublequote (optional) + spaces + capital letter. 
- I haven't preserved tags if it gets down to removing the last sentence. 
*/ 
function removeLastSentence(text) { 

    lastSeparator = Math.max(
     text.lastIndexOf("."), 
     text.lastIndexOf("!"), 
     text.lastIndexOf("?") 
    ); 

    revtext = text.split('').reverse().join(''); 
    sep = revtext.search(/[A-Z]\s+(\")?[\.\!\?]/); 
    lastTag = text.length-revtext.search(/\/\</) - 2; 

    lastPtr = (lastTag > lastSeparator) ? lastTag : text.length; 

    if (sep > -1) { 
     text1 = revtext.substring(sep+1, revtext.length).trim().split('').reverse().join(''); 
     text2 = text.substring(lastPtr, text.length).replace(/['"]/g,'').trim(); 

     sWithoutLastSentence = text1 + text2; 
    } else { 
     sWithoutLastSentence = ''; 
    } 
    return sWithoutLastSentence; 
} 

/* 
TESTS: 

var text = '<p>Blabla, some more text here. Sometimes <span>basic</span> html code is used but that should not make the "selection" of the text any harder! I looked up the window and I saw a plane flying over. I asked the first thing that came to mind: "What is it doing up there?" She did not know, "I think we should move past the fence!", she quickly said. He later described it as: "Something insane. "</p>'; 

alert(text + '\n\n' + removeLastSentence(text)); 
alert(text + '\n\n' + removeLastSentence(removeLastSentence(text))); 
alert(text + '\n\n' + removeLastSentence(removeLastSentence(removeLastSentence(text)))); 
alert(text + '\n\n' + removeLastSentence(removeLastSentence(removeLastSentence(removeLastSentence(text))))); 
alert(text + '\n\n' + removeLastSentence(removeLastSentence(removeLastSentence(removeLastSentence(removeLastSentence(text)))))); 
alert(text + '\n\n' + removeLastSentence(removeLastSentence(removeLastSentence(removeLastSentence(removeLastSentence(removeLastSentence(text))))))); 
alert(text + '\n\n' + removeLastSentence('<p>Blabla, some more text here. Sometimes <span>basic</span> html code is used but that should not make the "selection" of the text any harder! I looked up the ')); 
*/ 
+0

Grazie per il tuo codice! – bartolsthoorn

+0

Ho riscritto la tua voce in coffeescript https://gist.github.com/1270335 – bartolsthoorn

Problemi correlati