Javascript:如何最有效地将数组连接到少于64个字符的块中?

Javascript:如何最有效地将数组连接到少于64个字符的块中?,javascript,arrays,string,algorithm,bin-packing,Javascript,Arrays,String,Algorithm,Bin Packing,我有一个非常长的名称数组,如下所示: namelist = [ "Andrew Alexander Brown", "Charlie Christopher Drake", "Edward Elsevier Furlong", "Gareth Gates Harper", "Indiana Chewbacca Jones", "Kevin M Lamarr", "Michael Randy Newman", "Oliver Terry Pratchett", "Queen Liz Regina"

我有一个非常长的名称数组,如下所示:

namelist = [ "Andrew Alexander Brown", "Charlie Christopher Drake", "Edward Elsevier Furlong", "Gareth Gates Harper", "Indiana Chewbacca Jones", "Kevin M Lamarr", "Michael Randy Newman", "Oliver Terry Pratchett", "Queen Liz Regina", "Stuart Townsend", "Umar Vespa", "Woodford X Xanadu", "Yanick Zebra" ];
我想将列表中的名称提取为字符串,每个名称由管道字符(|)分隔。每个新字符串应小于48个字符,例如,输出应如下所示(但小于或等于48个字符):

我希望新字符串的数量尽可能少,可能不需要维护数组中字符串的顺序——但我不知道如何在javascript中做到这一点

我知道我可以做一些类似于在名字列表中循环并将下一个名字添加到临时字符串中的事情。检查此临时字符串的长度,如果超过48个字符,则将其输出。继续循环,直到我们的名字用完,但这似乎不是很有效。例如,如果一个短名称后跟一个非常长的名称,那么字符(可以由临时字符串中另一个较小的名称填充)将被浪费

有没有关于如何最好地实现这一点的建议?

var-namelist=[“安德鲁·亚历山大·布朗”、“查理·克里斯托弗·德雷克”、“爱德华·埃尔塞维尔·弗隆”、“加雷思·盖茨·哈珀”、“印第安纳州丘巴卡·琼斯”、“凯文·M·拉马尔”、“迈克尔·兰迪·纽曼”、“奥利弗·特里·普拉切特”、“利兹·雷吉纳女王”、“斯图亚特·汤森德”、“乌马尔·维斯帕”、“伍德福德X上都”,“亚尼克斑马”];
var namelist= ["Andrew Alexander Brown", "Charlie Christopher Drake", "Edward Elsevier Furlong", "Gareth Gates Harper", "Indiana Chewbacca Jones", "Kevin M Lamarr", "Michael Randy Newman", "Oliver Terry Pratchett", "Queen Liz Regina", "Stuart Townsend", "Umar Vespa", "Woodford X Xanadu", "Yanick Zebra"];

var c48= [], next, temp= '', i= 0, L= namelist.length;
while(i<L){
    next= namelist[i++];
    if((temp+next).length<= 47) temp=temp? temp+'|'+next: next;
    else{
        c48.push(temp);
        temp= next;
    }
}

if(next)c48.push(next);
c48.join('\n')

/*  returned value: (String)
Andrew Alexander Brown|Charlie Christopher Drake
Edward Elsevier Furlong|Gareth Gates Harper
Indiana Chewbacca Jones|Kevin M Lamarr
Michael Randy Newman|Oliver Terry Pratchett
Queen Liz Regina|Stuart Townsend|Umar Vespa
Yanick Zebra
*/
var c48=[],next,temp='',i=0,L=namelist.length; 而(i这就是所谓的

解决方案将取决于您对高效的定义,更高效的装箱往往需要更长的计算时间。但效率较低的装箱往往需要更少的计算资源(可以认为在计算资源方面更高效)

这是我使用ECMA5规范的解决方案,它牺牲了计算资源,有利于更高效的装箱

我选择将
powerSet
函数保留为通用函数,这意味着它可以用于其他目的。正如@Bergi所强调的,如果您创建了一个自定义函数,其中包含
joinStringsMaxCharacters过滤器
,您可能会在计算资源方面获得更好的效率颂歌>

Javascript

一般功能

辅助功能

带连接线的包装箱

打包箱子并显示每个箱子的内容

输出

Kevin M Lamarr|Stuart Townsend|Woodford X Xanadu Michael Randy Newman|Queen Liz Regina|Umar Vespa Charlie Christopher Drake|Oliver Terry Pratchett Edward Elsevier Furlong|Indiana Chewbacca Jones Andrew Alexander Brown|Gareth Gates Harper Yanick Zebra Kevin M Lamarr | Stuart Townsend | Woodford X Xanadu 迈克尔·兰迪·纽曼|利兹·里贾纳女王|乌马尔·维斯帕 查理·克里斯托弗·德雷克|奥利弗·特里·普拉切特 Edward Elsevier Furlong |印第安纳州丘巴卡-琼斯 安德鲁·亚历山大·布朗|加雷斯·盖茨·哈珀 亚尼克斑马
关于

Bin packing问题。很高兴看到你的解决方案,这样就不会重复了。哇,Xotic750!这看起来太棒了,我正在努力理解其中的任何一个问题。我打算明天回到我的主计算机后发布我的解决方案,但与你的解决方案相比,这算不了什么(我的是一个带有while/for循环和ifs的黑客)再次。哇。这个代码很难理解。请使用
reduce
而不是
过滤器
一起使用
。此外,为了提高效率,您可以将第一个
过滤器
放入动力集生成器中。@Bergi是的,我想它可能会更好。我会尝试留出一点时间来做您的建议。@Bergi Up答案是过时的,但没有包括你所有的建议。这对你来说更好吗?@Bergi感谢这些额外的建议,在某些浏览器中似乎会有更好的性能。
function powerSet(array) {
    var lastElement,
        sets;

    if (!array.length) {
        sets = [[]];
    } else {
        lastElement = array.pop();
        sets = powerSet(array).reduce(function (previous, element) {
            previous.push(element);
            element = element.slice();
            element.push(lastElement);
            previous.push(element);

            return previous;
        }, []);
    }

    return sets;
}
function isString(element) {
    return typeof element === 'string';
}

function isNotUsed(element) {
    return this.every(function (u) {
        return u.indexOf(element) === -1;
    });
}

function sumLength(s, el) {
    return s + el.length;
}
function joinStringsMaxCharacters(arrayOfStrings, numberOfCharacters, separator) {
    if (!Array.isArray(arrayOfStrings) || !arrayOfStrings.every(isString)) {
        throw new TypeError('arrayOfStrings is not an array of strings!');
    }

    numberOfCharacters = numberOfCharacters >>> 0;
    if (!separator || !isString(separator)) {
        separator = '|';
    }

    var arrayLength = arrayOfStrings.length;

    return powerSet(arrayOfStrings).filter(function (set) {
        return set.length && (set.length === 1 || set.reduce(sumLength, set.length - 1) <= numberOfCharacters);
    }).sort(function (a, b) {
        return b.reduce(sumLength, b.length) - a.reduce(sumLength, a.length) || b.length - a.length;
    }).reduce(function (used, cur) {
        if (used.reduce(sumLength, 0) < arrayLength && cur.every(isNotUsed, used)) {
            used.push(cur);
        }

        return used;
    }, []).map(function (bin) {
        return bin.join(separator);
    });
}
var nameList = [
    "Andrew Alexander Brown",
    "Charlie Christopher Drake",
    "Edward Elsevier Furlong",
    "Gareth Gates Harper",
    "Indiana Chewbacca Jones",
    "Kevin M Lamarr",
    "Michael Randy Newman",
    "Oliver Terry Pratchett",
    "Queen Liz Regina",
    "Stuart Townsend",
    "Umar Vespa",
    "Woodford X Xanadu",
    "Yanick Zebra"];
joinStringsMaxCharacters(nameList, 48).forEach(function (bin) {
    console.log(bin);
});
Kevin M Lamarr|Stuart Townsend|Woodford X Xanadu Michael Randy Newman|Queen Liz Regina|Umar Vespa Charlie Christopher Drake|Oliver Terry Pratchett Edward Elsevier Furlong|Indiana Chewbacca Jones Andrew Alexander Brown|Gareth Gates Harper Yanick Zebra