C ++中(整个)单词的拆分

时间:2015-12-15 10:56:48

标签: c++ string text split

假设我们有一个必须由一组工作人员处理的文本(map / reduce项目中的映射器):文本的每个部分(拆分)必须一致(没有单词可以在两个工人之间分开)并且分裂的大小应该尽可能相等(负载平衡)。

这是我的算法:

  1. 将文本除以等分割,每个分别由off_t beginoff_t end(文本中的起始和结束字节)组成。
  2. 使每个分割保持一致:如果分割在单词的中间结束,则跳转到下一个空格(并对开头执行相同操作)。没有这个阶段,结果可能是错误的:想想着名的"字数" map / reduce中的示例。
  3. 输入(文字长度= 29个字符):

    Hello Darkness my old friend

    第1阶段有4名工人(〜=每名工人7个字符):

    |Hello D|arkness| my old| friend|

    阶段2:

    |Hello Darkness| |my old |friend|

    这是每次拆分的第2阶段代码:

            ifstream ifs (file , ifstream::in);
            char c;
            string s;
            if(begin>0){//begin=0 then first split: cannot break a word!
                //if char before the first one is different from ' ' or '\n'
                //then the split begins in the middle of a word (bad)
                ifs.seekg(begin-1,ios::beg);
                ifs.get(c);
                if(c!=' ' && c!='\n'){
                    getline(ifs,s,' '); //jump to the next white space
                    begin+=s.length();
                }
                if(begin>end)
                    end=begin;
            }
            ifs.seekg(end,ios::beg);
            ifs.get(c);
            if(c!=' ' && c!='\n' && end != size){
                getline(ifs,s,' ');
                end+=s.length();
            }
    

    如您所见,此解决方案有两个问题:

    1. 拆分大小可能不平衡(查看第一个和第二个拆分!)
    2. 代码有点棘手
    3. 您是否有任何改进解决方案的建议(在优雅和/或性能方面)?

2 个答案:

答案 0 :(得分:0)

我认为在算法上,你不能做得更好(如果你正在做Map | Reduce你可能有 lot 的数据,所以差别很小)。将分组排列为Hello| Darkness| my old| friend的工作将会过度。

略有改善可能是:

  • 估算第一次拆分的位置(本例中为字符7)
  • 阅读。
  • 向前看并返回以获取最近的空间。
  • 拆分。
  • 如果您已经搜索过,那么您已经掌握了下一个块的开头。
  • 更新您对下一个块的持续时间的估计。
  • 循环

唯一的麻烦是这会使代码甚至更多复杂。

答案 1 :(得分:0)

你也可以向后检查并使用较少的字符,直到空格。但是,这会导致额外的复杂性。对于这个简单的情况,它并不重要,因为我希望这些小部件的处理速度如此之快,以至于没有任何明显的差异。

随着分割的大小增加(比如说500个字符甚至一个兆字节),如果单词会保持相对较短,那么不平衡将变得越来越不重要 - 所以我也不会打扰,我会"保持简单,愚蠢" (KISS)。