You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHP中生成指定行数的单词字符串所有换行排列及最优分割?

嘿,这个问题我之前也遇到过类似的场景!咱们一步步来解决:首先得搞定生成所有可能的换行组合,再从中筛选出行长差异最小的结果。

第一步:先把句子拆成单词数组

首先得把输入的句子拆解成独立的单词,还要处理可能的首尾空格或者多个连续空格的情况:

$words = array_filter(explode(' ', trim($sentence)));

比如输入"My name is Gary",会得到["My", "name", "is", "Gary"]这个干净的单词数组。

第二步:生成所有符合要求的换行排列

核心逻辑是:如果有n个单词,要分成y行,就需要在n-1个单词间隙中选y-1个位置作为换行点(因为每行至少要有1个单词)。咱们可以用递归的方式来生成所有可能的组合:

function generateAllLineBreaks(array $words, int $lines): array {
    $result = [];
    $wordCount = count($words);
    
    // 边界情况处理:行数比单词数多,没法合理拆分(可以根据需求调整,比如每行一个单词+空行)
    if ($lines > $wordCount) {
        return array_map(fn($word) => [$word], $words);
    }
    // 行数等于单词数,只有一种分法:每行一个单词
    if ($lines === $wordCount) {
        return array_map(fn($word) => [$word], $words);
    }
    
    // 递归生成所有分割组合
    $generate = function($startIndex, $remainingLines, $currentGroup) use (&$generate, $words, $wordCount, &$result) {
        // 剩下最后一行时,把剩余所有单词打包进去
        if ($remainingLines === 1) {
            $currentGroup[] = implode(' ', array_slice($words, $startIndex));
            $result[] = $currentGroup;
            return;
        }
        
        // 遍历所有可能的当前行结束位置(要给剩下的行留至少一个单词)
        for ($i = $startIndex; $i <= $wordCount - $remainingLines; $i++) {
            $newGroup = $currentGroup;
            // 把从start到i的单词拼成当前行
            $newGroup[] = implode(' ', array_slice($words, $startIndex, $i - $startIndex + 1));
            // 递归处理剩下的单词和行数
            $generate($i + 1, $remainingLines - 1, $newGroup);
        }
    };
    
    $generate(0, $lines, []);
    return $result;
}

比如调用generateAllLineBreaks(["My", "name", "is", "Gary"], 2),会返回三种组合:

[["My", "name is Gary"], ["My name", "is Gary"], ["My name is", "Gary"]]
第三步:筛选出行长差异最小的组合

咱们可以用方差来衡量各行长度的差异(方差越小,整体长度越均匀),然后找出方差最小的组合:

// 计算一组行的长度方差(值越小,长度差异越小)
function calculateLineVariance(array $lineGroup): float {
    $lengths = array_map('strlen', $lineGroup);
    $average = array_sum($lengths) / count($lengths);
    $varianceSum = 0;
    foreach ($lengths as $len) {
        $varianceSum += pow($len - $average, 2);
    }
    return $varianceSum / count($lengths);
}

// 主函数:整合所有逻辑
function formatLines(string $sentence, int $lines): array {
    $words = array_filter(explode(' ', trim($sentence)));
    $allGroups = generateAllLineBreaks($words, $lines);
    
    if (empty($allGroups)) {
        return [$sentence]; // 异常情况直接返回原句
    }
    
    // 遍历所有组合,找到方差最小的那个
    $minVariance = PHP_FLOAT_MAX;
    $bestGroup = [];
    foreach ($allGroups as $group) {
        $currentVariance = calculateLineVariance($group);
        if ($currentVariance < $minVariance) {
            $minVariance = $currentVariance;
            $bestGroup = $group;
        }
    }
    
    return $bestGroup;
}

测试你的例子:formatLines("My name is Gary", 2),会返回["My name", "is Gary"]——因为这两行的长度都是7,方差为0,是最均匀的组合。

内容的提问来源于stack exchange,提问作者Joeseppi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 12:31:13