按字母表列出,将条目较少的字母组合在一起(PHP或JS)


Listing by alphabet, groups letters with few entries together (PHP or JS)

我正在开发一个包含长列表名称的Web应用程序。客户最初希望将名称按字母拆分为div,这样就可以很容易地跳转到列表中的特定名称。

现在,查看列表,客户指出了几个只有一两个名字的字母。他现在想知道,如果每个字母中只有几个名字,我们是否可以组合几个连续的字母。

(请注意,没有名字的字母根本不会显示。)

我现在要做的是让数据库服务器返回一个排序列表,然后保留一个包含当前字符的变量。我浏览名称列表,增加字符,并在到达每个字母时打印开头和结尾的divul标签。我知道如何调整这个代码来组合一些字母,但是,有一件事我不确定如何处理,那就是特定的字母组合是否是最好的组合。换句话说,说我有:

  • A-12个名称
  • B-2个名称
  • C-1名称
  • D-1名称
  • E-1名称
  • F-23个名称

我知道如何最终得到一个组A-C,然后自己拥有D。我正在寻找一种有效的方式来实现A应该是自己的,然后B-D应该在一起。

我真的不知道从哪里开始考虑这个问题。

如果有任何不同,这段代码将用于Kohana框架模块。


更新2012-04-04:

以下是我需要的澄清:

假设一组中我想要的最小项目数是30。现在假设字母A有25个项目,字母B、C和D各有10个项目,而字母E有32个项目。我想让A一个人呆着,因为把B+C+D结合起来会更好。组合它们的简单方法是A+B,C+D+E——这不是我想要的。

换言之,我需要每个小组中最接近最小值的最佳人选。

如果一个字母包含10个以上的名称,或者您设置了任何合理的限制,请不要将其与下一个字母组合。然而,如果你开始组合字母,如果你愿意的话,你可能会一直运行到收集到15个左右的名字,只要每个字母的名字都不超过10个。这不是一个通用的解决方案,但这是我解决它的方法。

我使用PHP开发了这个函数。它将包含超过$ammount名称的字母分组。

function split_by_initials($names,$ammount,$tollerance = 0) {
    $total = count($names);
    foreach($names as $name) {
        $filtered[$name[0]][] = $name;
    }
    $count = 0;
    $key = '';
    $temp = array();
    foreach ($filtered as $initial => $split) {
        $count += count($split);
        $temp = array_merge($split,$temp);
        $key .= $initial.'-'; 
        if ($count >= $ammount || $count >= $ammount - $tollerance) {
            $result[$key] = $temp;
            $count = 0;
            $key = '';
            $temp = array();
        }
    }
    return $result;
}

第三个参数用于将组限制为一个没有指定弹药数量但足够接近的字母。

类似于我想30人一组但是a有25为此,如果您将收费标准设置为5,则a将被单独保留,其他字母将被分组。

我忘了提一下,但它返回了一个多维数组,其中包含的字母作为关键字,然后是包含的名称。类似的东西

大堆([AB-C-]=>阵列([0]=>班迪斯·伯根[1] =>Arey Lowell[2] =>卡门·米兰达))

这并不完全是你所需要的,但我认为它已经足够接近了。

使用mrsherman放的jsfiddle,我想出了一些可行的方法:http://jsfiddle.net/F2Ahh/

显然,要将其用作伪代码,可以应用一些使其更高效的技术。但这就完成了任务。

Javascrip版本:具有排序和符号分组的增强版

function group_by_initials(names,ammount,tollerance) {
        tolerance=tollerance||0;
        total = names.length;
        var filtered={}
        var result={};
        $.each(names,function(key,value){
            val=value.trim();
            var pattern = /[a-zA-Z0-9&_'.-]/
            if(val[0].match(pattern)) {
                intial=val[0];
            }
            else
            {
                intial='sym';
            }
            if(!(intial in filtered))
                filtered[intial]=[];
            filtered[intial].push(val);
        })
        var count = 0;
        var key = '';
        var temp = [];
        $.each(Object.keys(filtered).sort(),function(ky,value){
            count += filtered[value].length;
            temp = temp.concat(filtered[value])
            key += value+'-'; 
            if (count >= ammount || count >= ammount - tollerance) {
                key = key.substring(0, key.length - 1);
                result[key] = temp;
                count = 0;
                key = '';
                temp = [];
            }
        }) 
        return result;
    }