Javascript—在单个数组中生成所有元素组合(成对)

Javascript—在单个数组中生成所有元素组合(成对),javascript,arrays,algorithm,combinations,Javascript,Arrays,Algorithm,Combinations,关于如何在数组中生成所有可能的元素组合,我见过几个类似的问题。但我很难弄明白如何编写一个只输出组合对的算法。任何建议都将不胜感激 从以下数组开始(包含N个元素): 并得到以下结果: var result = [ "apple banana" "apple lemon" "apple mango" "banana lemon" "banana mango" "lemon mango" ]; 我尝试了以下方法,但这会产生所有可能的组合,而不是组合对 var le

关于如何在数组中生成所有可能的元素组合,我见过几个类似的问题。但我很难弄明白如何编写一个只输出组合对的算法。任何建议都将不胜感激

从以下数组开始(包含N个元素):

并得到以下结果:

var result = [
   "apple banana"
   "apple lemon"
   "apple mango"
   "banana lemon"
   "banana mango"
   "lemon mango"
];
我尝试了以下方法,但这会产生所有可能的组合,而不是组合对

var letters = splSentences;
var combi = [];
var temp= "";
var letLen = Math.pow(2, letters.length);

for (var i = 0; i < letLen ; i++){
    temp= "";
    for (var j=0;j<letters.length;j++) {
        if ((i & Math.pow(2,j))){ 
            temp += letters[j]+ " "
        }
    }
    if (temp !== "") {
        combi.push(temp);
    }
}
var字母=句子;
var combi=[];
var temp=“”;
var letLen=数学功率(2,字母长度);
对于(变量i=0;i
使用ECMAScript:

var数组=[“苹果”、“香蕉”、“柠檬”、“芒果”];
var result=array.flatMap(
(v,i)=>array.slice(i+1).map(w=>v+''+w)
);
console.log(结果);
尝试以下操作:

var数组=[“苹果”、“香蕉”、“柠檬”、“芒果”];
var结果=[];

对于(var i=0;i一个简单的方法是在数组上执行双for循环,在该循环中跳过第二个循环中的第一个
i
元素

let数组=[“苹果”、“香蕉”、“柠檬”、“芒果”];
让结果=[];
//既然你只想要一双,那就没有理由了
//直接迭代最后一个元素
for(设i=0;iconsole.log(results);
虽然已经找到了解决方案,但我在这里发布了一个用于一般情况的算法,用于查找
m(m>n)
元素的所有组合大小
n
。在您的情况下,我们有
n=2
m=4

const result=[];
result.length=2;//n=2
功能联合收割机(输入、透镜、启动){
如果(len==0){
console.log(result.join(“”);//在这里处理结果
返回;
}

对于(让i=start;i使用
map
flatMap
可以执行以下操作(
flatMap
仅在上受支持)


在数组中生成元素组合很像在数字系统中计数, 其中,基数是数组中的元素数(如果考虑到将丢失的前导零)

这将为您提供数组的所有索引(串联):

您只对两对感兴趣,因此相应地限制范围:

range = (from, to) = [...Array(to).keys()].map(el => el + from)
indices = range => range.map(x => x.toString(base).padStart(2,"0"))

indices( range( 0, Math.pow(base, 2))) // range starts at 0, single digits are zero-padded.
现在剩下要做的是将索引映射到值

由于您不希望元素与其自身配对,因此顺序无关紧要, 在映射到最终结果之前,需要删除这些内容

const range=(from,to)=>[…数组(to).keys()].map(el=>el+from)
常数组合=arr=>{
常数基=arr.length
返回范围(0,数学功率(基数,2))
.map(x=>x.toString(base).padStart(2,“0”))
.filter(i=>!i.match(/(\d)\1/)和&i===i.split(“”).sort().join(“”))
.map(i=>arr[i[0]+“”+arr[i[1]])
}

log(组合([“苹果”、“香蕉”、“柠檬”、“芒果”)
在我的例子中,我希望根据数组的大小范围获得如下组合:

function getCombinations(valuesArray: String[])
{

var combi = [];
var temp = [];
var slent = Math.pow(2, valuesArray.length);

for (var i = 0; i < slent; i++)
{
    temp = [];
    for (var j = 0; j < valuesArray.length; j++)
    {
        if ((i & Math.pow(2, j)))
        {
            temp.push(valuesArray[j]);
        }
    }
    if (temp.length > 0)
    {
        combi.push(temp);
    }
}

combi.sort((a, b) => a.length - b.length);
console.log(combi.join("\n"));
return combi;
}
控制台中的输出:

该功能基于以下文档的逻辑,更多信息请参见以下参考:

如果((i&Math.pow(2,j)))

将第一个值的每一位与第二个值进行比较,如果匹配则视为有效,否则返回零且不满足条件


只是给下一个搜索它的人一个选项

const arr=['a','b','c']
常量组合=([head,…tail])=>tail.length>0?[…tail.map(tailValue=>[head,tailValue]),…组合(tail)]:[]

log(combinations(arr))/['a','b'],['a','c'],['b','c']]]
我最终为这个问题写了一个通用的解决方案,它在功能上与答案相当,但我在这里分享它,因为我认为它更容易阅读/理解,而且还充满了描述算法的注释


/**
*生成数组的所有组合。
*@param{Array}sourceArray-输入元素的数组。
*@param{number}comboLength-所需的组合长度。
*@return{Array}组合数组的数组。
*/
函数生成组合(sourceArray,comboLength){
const sourceLength=sourceArray.length;
if(comboLength>sourceLength)返回[];
const combos=[];//存储生成的有效组合。
//接受部分组合,一个到sourceArray的索引,
//以及创建完整长度组合所需添加的元素数。
//递归调用以构建组合,在每个调用深度添加后续元素。
const makeNextCombos=(工作组合、当前索引、剩余计数)=>{
const oneAwayFromComboLength=remainingCount==1;
//对于要添加到工作组合中的每个剩余元素。
对于(让sourceIndex=currentIndex;sourceIndex
我认为这是对所有这些问题的回答

/**
* 
*生成给定数组或数字的所有组合
* 
*@param{Array | number}item-item接受数组或数字。如果是数组,则导出所有项目组合。如果是数字,则导出所有数字组合
*@param{number}n-
var array = ["apple", "banana", "lemon", "mango"]
array.flatMap(x => array.map(y => x !== y ? x + ' ' + y : null)).filter(x => x)
arr = ["apple", "banana", "lemon", "mango"]
base = arr.length

idx = [...Array(Math.pow(base, base)).keys()].map(x => x.toString(base))
range = (from, to) = [...Array(to).keys()].map(el => el + from)
indices = range => range.map(x => x.toString(base).padStart(2,"0"))

indices( range( 0, Math.pow(base, 2))) // range starts at 0, single digits are zero-padded.
function getCombinations(valuesArray: String[])
{

var combi = [];
var temp = [];
var slent = Math.pow(2, valuesArray.length);

for (var i = 0; i < slent; i++)
{
    temp = [];
    for (var j = 0; j < valuesArray.length; j++)
    {
        if ((i & Math.pow(2, j)))
        {
            temp.push(valuesArray[j]);
        }
    }
    if (temp.length > 0)
    {
        combi.push(temp);
    }
}

combi.sort((a, b) => a.length - b.length);
console.log(combi.join("\n"));
return combi;
}
// variable "results" stores an array with arrays string type
let results = getCombinations(['apple', 'banana', 'lemon', ',mango']);
> (2) [1, 2]
> (2) [1, 3]
> (2) [2, 3]