Waarom is mijn woord gehakt?

Ik probeer tekst op een vaste lengte te hakken, maar ik wil geen woorden halveren, dus ik moet zoiets doen:

function fixedLength(str, len, bol) {
    var i, l = str.length, left = 0, right = l - 1, rtn, tmp;

    tmp = str.charAt(len);

    if (bol || tmp === " " || tmp === "") {
        rtn = str.substr(0, len);
    } else {
        tmp = len - 1;

        for (i = tmp; i > -1; i--) {
            if (str.charAt(i) === " ") {
                left = i;
                break;
            }
        }

        for (i = tmp; i < l; i++) {
            if (str.charAt(i) === " ") {
                right = i;
                break;
            }
        }

        rtn = str.substr(0, ((Math.abs(left - tmp) <= Math.abs(right - tmp)) ? left : right));
    }

    return rtn + "...";
}

Maar als ik het hiermee gebruik:

var str = "the quick brown fox jumped over the lazy dog";

for (var i = 0; i < 45; i++) {
    document.write("i:" + i + " - " + fixedLength(str, i) + "
"); }

Iedereen lijkt correct te werken, behalve in deze regel "i: 43 - de vlugge bruine vos sprong over de luie do ..." , het woord "hond" is gehakt ( Demo )

Ik kan de fout niet vinden, elke keer dat ik iets verander, voeg ik nieuwe bugs toe

3
Nou voor een, de kat in je gravatar ziet er erg verdacht uit ...
toegevoegd de auteur tskuzzy, de bron
Voor degenen die te lui waren om de bewerkingsgeschiedenis te controleren, was de originele titel: "Waarom was mijn hond gehakt :(?" Het was een epische titel. Ik vind het jammer om te zien dat het is bewerkt :-(
toegevoegd de auteur Platinum Azure, de bron
Is dit geen hulp: jsfiddle.net/YXwfb/1 ? In principe zoekt dit naar de laatste woordgrens in len tekens.
toegevoegd de auteur Kobi, de bron

5 antwoord

Heeft uw code niet gecontroleerd, maar u zou uw code eenvoudiger kunnen schrijven:

function fixedLength(str, len, bol) {
    while(!bol && str[len] && str[len] !== ' ') {
      len--;
    }
    return str.substr(0, len) + '...';
}

En de demo .

4
toegevoegd
nou, mijn code hakte het woord in, afhankelijk van de positie, als het hier was abXcde was het niet inbegrepen, maar abcXde was het, enz. Maar ik denk dat deze functie stom en ik zal gewoon je oplossing gebruiken. Hoewel mijn vraag was om de bron van fouten te vinden, denk ik dat een oplossing die het onnodig maakt om de fout te repareren, ook kandidaat moet zijn om geaccepteerd te worden, ja ... Ik accepteer dit, bedankt
toegevoegd de auteur ajax333221, de bron
@ ajax333221 Ja, één functie om één ding te doen, KISS :)
toegevoegd de auteur xdazz, de bron

In het geval dat je geïnteresseerd bent, zat de bug in je originele code in de laatste toewijzing van de geretourneerde waarde, waarbij je tmp - links en tmp - rechts vergeleek. Het probleem is dat in het geval van het laatste woord in de reeks, "hond", recht nooit opnieuw wordt toegewezen nadat de beginwaarde ervan is ingesteld op 1 - 1; en dus werkt je algoritme alsof een spatie werd gevonden bij index 44, terwijl er in feite een g is.

1
toegevoegd

U zou kunnen proberen om met Regex het laatste teken ruimte te vinden.

function fixedLength(str, len, bol) {
    if(str.length <= len) {
       return str;  
    }

    var rtn = str.substr(0, len).match(/.* /);
    if(rtn == null) {
        rtn = "";
    } else {
        rtn = rtn + "...";
    }
    return rtn;
}

Demo here: http://jsfiddle.net/R8qMQ/2/

Ik heb ook een verificatie toegevoegd, als de invoerreeks zich al binnen de toegestane lengte bevindt, geef je deze eenvoudig terug. Als er geen woorden zijn die kunnen worden gesplitst, retourneert u een lege tekenreeks in plaats van NULL.

Ik zou met regex gaan omdat ik in de toekomst ook andere tekens zou kunnen toevoegen die ik als scheidingstekens voor woorden zou kunnen beschouwen (bijv. . of ; of misschien REGEX b - woordafbakening).

1
toegevoegd
<= length moet len zijn voor het geval dit niet voor de hand ligt
toegevoegd de auteur ajax333221, de bron
dankje voor de correctie
toegevoegd de auteur Stelian Matei, de bron
rtn = str.substr(0, ((Math.abs(left - tmp + 1) <= Math.abs(right - tmp)) ? left : right));

Ik heb het niet met een debugger opgelost, maar het gebruik van uw Demo was zeer nuttig.

0
toegevoegd

Ik heb geprobeerd je code op een begrijpelijke manier te refactoren:

function prettyCut(word, length) {
    //account for ellipses
    length -= 3;

    //break down into lengths
    var units = word.split(" ").map(function(word) {
        return word.length+1;
    });

    //map to accumulated sums
    var runningSum = 0;
    var sums = units.map(function(length, index) {
        return (runningSum += length)
    }); 

    //find difference from goal of each sum
    var differences = sums.map(function(sum) {
        return (length-sum)>0?(length-sum):100;
    });

    //minimize and return
    var closest = Math.min.apply(this, differences);
    return closest==0?word:word.substr(0, length-closest)+"...";
}
prettyCut("the quick brown fox jumped over the lazy dog", 45);
0
toegevoegd