2012-02-13 8 views
2

を分割する位置を覚えて、私は次の文字列を持っていると仮定します、その後2番目の8ワードの分割。いくつの単語を分割するかの後ろの位置は、配列(2、8、3)に格納されます。次に、文字列は、カスタム文字列タガーに渡さなければ爆縮さ:スプリット文字列、

tag_string('I have been very busy lately and need to go to bed early'); 

私はtag_stringの出力は合計言葉が同じままであることを除いて、正確にどうなるかわかりません。出力の例は次のようになります。

I have-nn been-vb very-vb busy lately and-rr need to-r go to bed early-p 
I-ee have been-vb very busy-df lately-nn and need-f to go to bed-uu early-yy 

これは、文字列を未知数で長くします。私はtag_stringを制御できません。私が知っていることは、(1)単語の数が以前と同じであること、(2)配列が2の後に分割された後に8ワード後になることです。出力で

$string = "I have-nn been-vb very-vb busy lately and-rr need to-r go to bed early-p" 
function split_string_again() { 
    // split after 2nd, and thereafter after 8th word 
} 

:私は今、解決策は、前と同じ配列にタグ付けされた文字列を爆発必要

$arr = array(
    [0] => I have-nn 
    [1] => been-vb very-vb busy lately and-rr need to-r go 
    [2] => to bed early-p 
) 

だから、明確にする(私は以前にはなかった):私は覚えることにより、分割することはできませんstrposは文字列の前後にstrposがあるため、同じではありません。私は言葉の数を数える必要があります。

+0

あなたはそれを爆発させ、配列の各部分を 'strlen'することができます – seanbreeden

+0

あなたがしようとしていることを聞くことに興味があります、もっと進んでいれば[Rope data structure] http://en.wikipedia.org/wiki/Rope_%28computer_science%29) - PHPでの実装は「遅い」可能性があります。 – tplaner

+0

@evolve私は今それをより良く説明したと思う - OPの編集を見なさい。 – Pr0no

答えて

1

興味深い質問は、rope data structureはまだ言葉の配置が変更されませんので、少しやり過ぎかもしれません適用されます。ここに私の解決策があります:

$str = "I have | been very busy lately and need to go | to bed early"; 

function get_breaks($str) 
{ 
    $breaks = array(); 
    $arr = explode("|", $str); 

    foreach($arr as $val) 
    { 
     $breaks[] = str_word_count($val); 
    } 

    return $breaks; 
} 

$breaks = get_breaks($str); 

echo "<pre>" . print_r($breaks, 1) . "</pre>"; 

$str = str_replace("|", "", $str); 

function rebreak($str, $breaks) 
{ 
    $return = array(); 
    $old_break = 0; 

    $arr = str_word_count($str, 1); 

    foreach($breaks as $break) 
    { 
     $return[] = implode(" ", array_slice($arr, $old_break, $break)); 

     $old_break += $break; 
    } 

    return $return; 
} 

echo "<pre>" . print_r(rebreak($str, $breaks), 1) . "</pre>"; 

echo "<pre>" . print_r(rebreak("I have-nn been-vb very-vb busy lately and-rr need to-r go to bed early-p", $breaks), 1) . "</pre>"; 

質問がありましたら教えてください。しかし、それはかなり自明です。これを改善する方法もあります。

+1

ありがとう!あなたの助けに感謝します。小さな見落としがありました。修正するのは簡単でした。$ old_break = $ break; $ old_break + = $ breakでなければならなかった。私はロープのデータ構造を見ていましたが、実際にはこの特定の操作だけが必要なので、残念です。 – Pr0no

+0

@Reveller良いキャッチ!一定。 – tplaner

3

単語の数を数えたくない場合は、文字列の長さ(strlen)を数えたいと思うでしょう。パイプなしの同じ文字列の場合は、一定量の後にsubstrで分割します。

$strCounts = array(); 

foreach ($arr as $item) { 
    $strCounts[] = strlen($item); 
} 

// Later on. 
$arr = array(); 
$i = 0; 
foreach ($strCounts as $count) { 
    $arr[] = substr($string, $i, $count); 
    $i += $count; // increment the start position by the length 
} 

私はこれをテストしていません。単純に「理論」であり、うまくいかないことがあります。それについてもっと良い方法があるかもしれませんが、私はそれを知らないだけです。

+2

'strlen'と単語数の+1。私はその質問が実際のソリューションメリットよりも複雑に見えると思う。 – rdlowrey

+0

strlenは解決策ではありませんが(私の質問ではわかりませんでしたので、そのように見えます)。編集されたOPをご覧ください。 – Pr0no

+1

私はしばらくしたら、それを見てみましょう:) –

1

私はあなたが実際に達成したかったことを理解しています。しかしここにあなたを助けるかもしれない2つの事柄があります:

str_word_count()は文字列の単語の数を数えます。 preg_match_all('/\p{L}[\p{L}\p{Mn}\p{Pd}\x{2019}]*/u', $string, $foo);はほとんど同じですが、UTF-8文字列を使用しています。

strpos()は、別の文字列内の文字列の最初の出現を検出します。あなたは簡単にすべての位置を見つけることができます|これで:

$pos = -1; 
$positions = array(); 
while (($pos = strpos($string, '|', $pos + 1)) !== false) { 
    $positions[] = $pos; 
} 

私はまだあなたがちょうどかかわらず、このためexplode()を使用できない理由を私は理解わかりません。私は思うものの

<?php 
$string = 'I have | been very busy lately and need to go | to bed early'; 
$parts = explode('|', $string); 
$words = array(); 
foreach ($parts as $s) { 
    $words[] = str_word_count($s); 
} 
+0

strposはここでは役に立ちません(私の質問ではっきりしていなかったので、このように見えましたが)。更新されたOPを見て、あなたの考えを教えてください。 – Pr0no