获取字符串的所有组合

Posted

技术标签:

【中文标题】获取字符串的所有组合【英文标题】:get all combinations for a string 【发布时间】:2012-08-16 10:19:35 【问题描述】:

我正在尝试在 javascript 中创建一个函数,给定一个字符串将返回一个包含所有可能的字母组合的数组,每个字母最多使用一次,从最短的开始。例如,对于字符串 ABC,它将返回:

A
B
C
AB
AC
ABC

我可以像这样使用循环:

for(i=0; i<string.length; i++) 
   //add string[i]

for(i=0; i<string.length; i++) 
    for(a=i; a<string.length; a++) 
            //add string[i]+string[a]
    

for(i=0; i<string.length; i++) 
    for(a=i; a<string.length; a++) 
        for(b=a; b<string.length; b++) 
            //add string[i]+string[a]+string[b]
        
    

但我不知道字符串的长度,所以不知道要使用多少个循环。

有什么想法吗?

编辑:我不是要求排列,不应同时返回 abc 和 acb。数组中最短的也很重要。

这不是家庭作业。这是一个解决“熄灯”类型游戏的程序。

【问题讨论】:

【参考方案1】:

这是一个我认为很容易理解的递归解决方案。

var tree = function(leafs) 
  var branches = [];
  if (leafs.length == 1) return leafs;
  for (var k in leafs) 
    var leaf = leafs[k];
    tree(leafs.join('').replace(leaf, '').split('')).concat("").map(function(subtree) 
      branches.push([leaf].concat(subtree));
    );
  
  return branches;
;
console.log(tree("abc".split('')).map(function(str) 
  return str.join('')
))

【讨论】:

这比其他函数提供了更多可能的结果,我认为这应该是大多数可能答案的正确答案。【参考方案2】:

您可以使用一个讨厌的技巧并增加一个计数器并将其二进制表示用作标志:

function combine(str)
   const result = [];
   for(let i = 1; i < Math.pow(2, str.length) - 1; i++)
      result.push([...str].filter((_, pos) => (i >> pos) & 1).join(""));
  return result;

console.log(combine('abcd'));

Jsbin

【讨论】:

这确实很快,但不包括与原始字符串长度相同的组合。例如,“ABC”也应该将“CBA”作为结果之一。是否对此进行了修改以包括这些组合? @sebastian 您正在寻找所有可能的排列,而不是组合【参考方案3】:

这就是我最终使用的。

var combinations = function (string)

    var result = [];

    var loop = function (start,depth,prefix)
    
        for(var i=start; i<string.length; i++)
        
            var next = prefix+string[i];
            if (depth > 0)
                loop(i+1,depth-1,next);
            else
                result.push(next);
        
    

    for(var i=0; i<string.length; i++)
    
        loop(0,i,'');
    

    return result;

【讨论】:

但是,我发现您的解决方案不符合 get all combinations 的意图。例如,doing combinations('dog') 给出了[ 'd', 'o', 'g', 'do', 'dg', 'og', 'dog' ],这不是所有组合god, go, gd 不见了。一个潜在的解决方案可能是将结果分成两部分,reverse() 后半部分,然后重新附加到原始结果以适应回文字符串的用例。 正如我在原始问题中所说,我不希望包含排列。在我的用例中,“狗”和“上帝”会得到相同的结果,因此是多余的。【参考方案4】:

这是使用循环,正如你所期望的最简单的方法.. 祝你好运

        function mixString() 
            var inputy = document.getElementById("mixValue").value
            var result = document.getElementById("mix-result")
            result.innerhtml=""

            
            for (var i = 0 ; i < inputy.length; i++) 
               
                for (var b = 0 ; b < inputy.length; b++) 
                    
                    if (i == b) 
                        
                        result.innerHTML += inputy.charAt(i) + ","
                    
                    else
                    
                        result.innerHTML += inputy.charAt(i) + inputy.charAt(b) + ","
                    
                    
                

            
        
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
    
    <div class="container">
        <div class="panel panel-default">
            <div class="panel-heading">JavaScript string combination
</div>
            <div class="panel-body">
                <input id="mixValue" class="form-control" />
                <input type="button" onclick="mixString()" value="click" />
                <div id="mix-result"></div>
            </div>
        </div>
    </div>

【讨论】:

【参考方案5】:
function combinations(var1) 

    var temp;

    for (var i = 0; i < var1.length; i++) 
        var2 = "";

        temp = i;

        while (temp < var1.length) 

            var2 = var2.concat(var1.charAt(temp));
            // console.log(var2)
            if (i == var1.length - 1)
                document.getElementById('result').innerHTML += var2;

            else
                document.getElementById('result').innerHTML += var2 + ',';
            temp++;
        
    

【讨论】:

【参考方案6】:

您可以通过使用或不使用给定键处的字符来采用迭代和递归方法。

function combine(string) 
    function iter(i, temp) 
        if (i >= string.length) 
            result.push(temp);
            return;
        
        iter(i + 1, temp + string[i]);
        iter(i + 1, temp);
    

    var result = [];
    iter(0, '');
    return result;


console.log(combine('jump'));
.as-console-wrapper  max-height: 100% !important; top: 0; 

【讨论】:

【参考方案7】:

自 2019 年 7 月 29 日起接受的解决方案允许在数组中返回重复的字符串。以下调整通过向推送添加条件来解决这个小问题。

            // however, we don't want duplicates so...
            if (!result.includes(next)) 
                result.push(next);    
            

【讨论】:

【参考方案8】:

生成器允许非常干净的实现:

// Very short generator produces all possible strings composed of the given chars!
let allStrings = function*(chars) 
  yield '';
  for (let prefix of allStrings(chars)) for (let c of chars) yield `$prefix$c`;
;

// Render the first 1000 strings
document.body.style.fontFamily = 'monospace';
let count = 0;
for (let str of allStrings('abcd')) 
  let div = document.createElement('div');
  div.innerHTML = `$(count + 1).toString().padStart(4, '0'): $str`;
  document.body.appendChild(div);
  if (count++ > 1000) break;

请注意,allStrings 的第一个结果是空字符串。如果避免这种情况至关重要,可以使用以下实现:

let allStrings = function*(chars, includeEmpty=false) 
  if (includeEmpty) yield '';
  for (let prefix of allStrings(chars, true)) for (let c of chars) yield `$prefix$c`;
;

【讨论】:

【参考方案9】:

//字符串的所有组合 // 狗 => d,do,dog,og,g

function combinationString()
    let str = 'dog';
    let combinationArray = [];

    for(i=0; i< str.length; i++)
        for(j=i+1; j<=str.length; j++)
            combinationArray.push(str.slice(i,j));
        
    
    console.log("Combination ", combinationArray);

combinationString()

【讨论】:

以上是关于获取字符串的所有组合的主要内容,如果未能解决你的问题,请参考以下文章

如何获取字符串的所有 1 位或相邻的 2 位组合

python:随机播放字符串中的字符以获取所有可能的字符串组合[重复]

获取字符串或组合的所有可能排列,包括 Java 中的重复字符

查找所有字符串拆分组合

如何根据字符串组合获取数据?

“程序收到信号SIGSEGV,分段错误”当试图使用递归获取3个字符组合的所有关键字时