最近遇到了一個(gè)關(guān)于商品屬性求組合的問(wèn)題,怕我描述不好先上圖:如下
1、旁邊的顏色尺碼什么的 數(shù)量都是不確定的(因?yàn)橛锌赡苁羌译姡称罚蛘叻b什么的)
2、右邊的屬性值是允許手動(dòng)添加的,所以數(shù)量也是不確定的
為了規(guī)范庫(kù)存啥的,所以要分別排列組合出各種規(guī)格的商品并添加庫(kù)存,我現(xiàn)在手動(dòng)取到了上面的值格式如下:
data = {
color:[value1,value2,value3,....],
size:[value1,value2,value3,....],
style:[value1,value2,value3,....]
}
然后我就不知道怎么求組合了,我主要是不知道如何遞歸,如何創(chuàng)建中間變量,求各位大佬給點(diǎn)思路,或者給出你們的代碼讓我參考一下,有注釋更好,感謝!?。?!深夜加班,我要哭了
湊個(gè)熱鬧。。。
這個(gè)數(shù)據(jù)結(jié)構(gòu)只有兩層,只是每一層的數(shù)量不確定。所以?xún)蓪友h(huán)就夠了,沒(méi)有必要遞歸。
var data = {
color: ['color1', 'color2', 'color3'],
size: ['size1', 'size2', 'size3'],
style: ['style1', 'style2', 'style3']
}
Object.values(data).reduce( (result, property) => {
return property.reduce( (acc, value) => {
return acc.concat(result.map( ele => [].concat(ele, value)));
}, []);
});
輸出結(jié)果為包含對(duì)象的數(shù)組:
// 循環(huán)每一個(gè)商品屬性
Object.keys(data).reduce( (result, key) => {
// 循環(huán)屬性的每一個(gè)值
return data[key].reduce( (acc, value) => {
// 對(duì)于第一個(gè)屬性
if (!result.length) {
// 將數(shù)值轉(zhuǎn)化為對(duì)象格式
return acc.concat({ [key]: value });
}
// 對(duì)于第一個(gè)之后的屬性,將新的屬性和值添加到已有結(jié)果,并進(jìn)行拼接。
return acc.concat( result.map( ele => (Object.assign({}, ele, { [key]: value }) )));
}, []);
}, []);總結(jié)了幾位大神的答案,我自己提出了一個(gè)新的需求,我想最終的數(shù)據(jù)格式是一個(gè)成員為對(duì)象的數(shù)組,對(duì)象包含的屬性就是我要使用的值,所以我消化了一下擼出了下面這段:
var data = {
size: ['size1', 'size2', 'size3'],
color: ['color1', 'color2', 'color3'],
style: ['style1', 'style2', 'style3']
};
var pr = (function(data){
var aa = [];
for(var pro in data){
aa.push(pro);
}
return aa;
})(data);
Object.values(data).reduce(function(objs,props,index){
debugger
if(objs.length==0){
return props.reduce(function(oo,att){
var oob = new Object();
oob[pr[index]] = att;
return oo.concat(oob);
},[]);
}else{
var item = objs.reduce(function(ritem,oo){
var tt = props.reduce(function(subitem,att){
var oob = new Object();
for(var i in oo){
oob[i] = oo[i];
}
oob[pr[index]] = att;
subitem.push(oob);
return subitem;
},[]);
return ritem.concat(tt)
},[]);
return item;
}
},[])熬夜加班不容易呀,我搜了下資料,結(jié)合別人的例子,自己寫(xiě)了個(gè)
你可以參考一下。
主要思路是遞歸組合前兩個(gè)
function handleCombine(arr) {
debugger
var len = arr.length;
if (len >= 2) {
//從前兩個(gè)開(kāi)始組合
var len1 = arr[0].length;
var len2 = arr[1].length;
var lenBoth = len1 * len2;
var items = new Array(lenBoth);
var index = 0;
//for循環(huán)構(gòu)建兩兩組合后的數(shù)組
for (var i = 0; i < len1; i++) {
for (var j = 0; j < len2; j++) {
if (arr[0][i] instanceof Array) {
items[index] = arr[0][i].concat(arr[1][j]);
} else {
items[index] = [arr[0][i]].concat(arr[1][j]);
}
index++;
}
}
// 新組合的數(shù)組取代原來(lái)前兩個(gè)數(shù)組
var newArr = new Array(len - 1);
for (var i = 2; i < arr.length; i++) {
newArr[i - 1] = arr[i];
}
newArr[0] = items;
// 再次組合前兩個(gè)
return handleCombine(newArr);
} else {
return arr[0];
}
}
var data = {
color: ['color1', 'color2', 'color3'],
size: ['size1', 'size2', 'size3'],
style: ['style1', 'style2', 'style3']
}
var multiArr = []
for (key in data) {
multiArr.push(data[key])
}
console.log(handleCombine(multiArr));這個(gè)問(wèn)題按照常規(guī),全排列的前提是知道對(duì)象里面的所有屬性,然后利用多種for循環(huán)或者簡(jiǎn)便的forEach語(yǔ)句進(jìn)行一一配對(duì)。
樓上已經(jīng)把解決方案都列出來(lái)了,我這里說(shuō)一下我的思考。
我在想能不能封裝一個(gè)方法,能夠自動(dòng)遍歷給定對(duì)象的所有屬性所對(duì)應(yīng)的值,然后將它們進(jìn)行全排列。這樣就不需要預(yù)先知道對(duì)象的所有key,只要保證它的結(jié)構(gòu)符合我們的要求即可。
這里要求的對(duì)象結(jié)構(gòu)是:
var data = {
key1: [val1, val2, ...],
key2: [val1, val2, ..],
key3: [val1, val2, ..],
...
};
經(jīng)過(guò)實(shí)踐,我封裝出來(lái)了一個(gè)generatePropertyValueArrange(obj)方法,只要保證這個(gè)obj這個(gè)對(duì)象的結(jié)構(gòu)符合我們的要求,就能夠保證輸出正確的所有對(duì)應(yīng)屬性值的數(shù)組的全排列組合。
思路如下:
先構(gòu)造出對(duì)象的所有屬性所對(duì)應(yīng)值的數(shù)組遍歷的forEach語(yǔ)句,類(lèi)似以下的語(yǔ)句,即
obj.key1.forEach(key1 => {
obj.key2.forEach(key2 => {
...
});
});
eval來(lái)執(zhí)行剛剛生成的forEach語(yǔ)句,這里有點(diǎn)像模板引擎的味道完整代碼如下:
// 構(gòu)建符合要求的對(duì)象
var data = {
color: ['red', 'blue', 'black'],
size: ['S', 'M', 'L'],
style: ['child', 'young', 'middle'],
height: ['short', 'high'],
// 這里可以添加形如key: [..., ...] 這種形式的項(xiàng)
};
// 調(diào)用構(gòu)造方法
var dataArrange = generatePropertyValueArrange(data);
// 輸出結(jié)果
console.log(dataArrange);
/*
* 生成對(duì)象的屬性值的全排列
* @return array
* */
function generatePropertyValueArrange(obj) {
var objKeys = Object.keys(obj);
var length = objKeys.length;
var statementChain = ''; // forEach的語(yǔ)句
var num = 0; // 記錄obj的key值遍歷的位置,比如color為0,size為1
var result = []; // 執(zhí)行結(jié)果存放的數(shù)組
getObjForEachStatement(); // 執(zhí)行獲取對(duì)象的forEach執(zhí)行語(yǔ)句
console.log(statementChain); // 打印以下執(zhí)行語(yǔ)句
eval(statementChain); // 執(zhí)行生成的forEach語(yǔ)句
// 返回result
return result;
/*
* 具體生成執(zhí)行語(yǔ)句的函數(shù),主要通過(guò)修改statementChain,num和result
* */
function getObjForEachStatement() {
var key = objKeys[num];
// 比如生成:obj['color'].forEach( color => {
statementChain += "obj['"+ key +"'].forEach( "+ key +" => {\n";
// 如果已經(jīng)是遍歷到最后一個(gè)屬性,那么push結(jié)果
if (num === length - 1) {
// 比如生成:color:color,size:size,style:style,height:height,
// 屬性名稱(chēng):屬性值的形式
var item = objKeys.reduce((acc, curr) => {
return acc.concat([curr, ':', curr].join('')).concat(',');
}, '');
// 添加到forEach語(yǔ)句中
// "});".repeat(length);的作用是封閉forEach語(yǔ)句
statementChain += "result.push({\n\t"+ item +"\n});" + "});".repeat(length);
}
num++;
if (num < length) {
// 屬性還沒(méi)有遍歷完,遞歸
getObjForEachStatement();
}
}
}
測(cè)試結(jié)果如下:
// 生成的forEach語(yǔ)句
obj['color'].forEach( color => {
obj['size'].forEach( size => {
obj['style'].forEach( style => {
obj['height'].forEach( height => {
result.push({
color:color,size:size,style:style,height:height,
});});});});});
// 構(gòu)造的全排列數(shù)組
[ { color: 'red', size: 'S', style: 'child', height: 'short' },
{ color: 'red', size: 'S', style: 'child', height: 'high' },
{ color: 'red', size: 'S', style: 'young', height: 'short' },
{ color: 'red', size: 'S', style: 'young', height: 'high' },
{ color: 'red', size: 'S', style: 'middle', height: 'short' },
{ color: 'red', size: 'S', style: 'middle', height: 'high' },
{ color: 'red', size: 'M', style: 'child', height: 'short' },
{ color: 'red', size: 'M', style: 'child', height: 'high' },
{ color: 'red', size: 'M', style: 'young', height: 'short' },
{ color: 'red', size: 'M', style: 'young', height: 'high' },
{ color: 'red', size: 'M', style: 'middle', height: 'short' },
{ color: 'red', size: 'M', style: 'middle', height: 'high' },
{ color: 'red', size: 'L', style: 'child', height: 'short' },
......
大概就這些。
let color = ['blue','red','white'];
let size = ['s','m','l'];
let style = [1,2,3];
let result = [];
for (var i = 0; i < color.length; i++) {
for (var j = 0; j < size.length; j++) {
for (var k = 0; k < style.length; k++) {
result.push({
color: color[i],
size: size[j],
style: style[k]
})
}
}
}
console.log(result);
北大青鳥(niǎo)APTECH成立于1999年。依托北京大學(xué)優(yōu)質(zhì)雄厚的教育資源和背景,秉承“教育改變生活”的發(fā)展理念,致力于培養(yǎng)中國(guó)IT技能型緊缺人才,是大數(shù)據(jù)專(zhuān)業(yè)的國(guó)家
達(dá)內(nèi)教育集團(tuán)成立于2002年,是一家由留學(xué)海歸創(chuàng)辦的高端職業(yè)教育培訓(xùn)機(jī)構(gòu),是中國(guó)一站式人才培養(yǎng)平臺(tái)、一站式人才輸送平臺(tái)。2014年4月3日在美國(guó)成功上市,融資1
北大課工場(chǎng)是北京大學(xué)校辦產(chǎn)業(yè)為響應(yīng)國(guó)家深化產(chǎn)教融合/校企合作的政策,積極推進(jìn)“中國(guó)制造2025”,實(shí)現(xiàn)中華民族偉大復(fù)興的升級(jí)產(chǎn)業(yè)鏈。利用北京大學(xué)優(yōu)質(zhì)教育資源及背
博為峰,中國(guó)職業(yè)人才培訓(xùn)領(lǐng)域的先行者
曾工作于聯(lián)想擔(dān)任系統(tǒng)開(kāi)發(fā)工程師,曾在博彥科技股份有限公司擔(dān)任項(xiàng)目經(jīng)理從事移動(dòng)互聯(lián)網(wǎng)管理及研發(fā)工作,曾創(chuàng)辦藍(lán)懿科技有限責(zé)任公司從事總經(jīng)理職務(wù)負(fù)責(zé)iOS教學(xué)及管理工作。
浪潮集團(tuán)項(xiàng)目經(jīng)理。精通Java與.NET 技術(shù), 熟練的跨平臺(tái)面向?qū)ο箝_(kāi)發(fā)經(jīng)驗(yàn),技術(shù)功底深厚。 授課風(fēng)格 授課風(fēng)格清新自然、條理清晰、主次分明、重點(diǎn)難點(diǎn)突出、引人入勝。
精通HTML5和CSS3;Javascript及主流js庫(kù),具有快速界面開(kāi)發(fā)的能力,對(duì)瀏覽器兼容性、前端性能優(yōu)化等有深入理解。精通網(wǎng)頁(yè)制作和網(wǎng)頁(yè)游戲開(kāi)發(fā)。
具有10 年的Java 企業(yè)應(yīng)用開(kāi)發(fā)經(jīng)驗(yàn)。曾經(jīng)歷任德國(guó)Software AG 技術(shù)顧問(wèn),美國(guó)Dachieve 系統(tǒng)架構(gòu)師,美國(guó)AngelEngineers Inc. 系統(tǒng)架構(gòu)師。