如何匹配两个对象之间的值并使用特定值创建新值

我有oDataSetaProperties对象的对象数组,我希望匹配在aPropertis和in aPropertis中找到的相同值,并创建aSelectedDataSet ,它在开头是一个空对象

如何在JS / Jquery中推荐它

注意:在循环/解决方案中不应该有任何硬编码 属性来进行匹配,aProperties包含这个值但是它可以改变(当然应该在oData对象中匹配…)

有关说明以下是如何构建对象的示例

http://jsfiddle.net/4rh6tt25/5/

这是输入

  //This is given array of object which can be many ,here I put just two instance in the array for demonstration purpose var oDataSet = [{ __metadata: { aaa: 111, bbb: 222 }, to_ExcludedTerms: {results: []}, to_ListTypeGroupAssignment: { results: [ { AuthorisationGroup: 'AuthorisationGroup 1', ListTypeGroup: 'ListTypeGroup1', ListTypeGroupDescription: 'ListTypeGroupDescription 1', ParentKey: '8ae25d47-c3cc-4ee3-a040-ea00505692111', __metadata: {} }, { AuthorisationGroup: 'AuthorisationGroup 2', ListTypeGroup: 'ListTypeGroup2', ListTypeGroupDescription: 'ListTypeGroupDescription 2', ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb7', __metadata: {} }, { AuthorisationGroup: 'AuthorisationGroup 3', ListTypeGroup: 'ListTypeGroup3', ListTypeGroupDescription: 'ListTypeGroupDescription 3', ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb5', __metadata: {} } ] } }, { //This is the second instance of the object with same keys but different values __metadata: { aaa: 333, bbb: 444 }, to_ExcludedTerms: {results: []}, to_ListTypeGroupAssignment: { results: [ { AuthorisationGroup: 'AuthorisationGroup 6', ListTypeGroup: 'ListTypeGroup6', ListTypeGroupDescription: 'ListTypeGroupDescription 6', ParentKey: '8ae25d47-c3cc-4ee3-a040-ea00505692116', __metadata: {} }, { AuthorisationGroup: 'AuthorisationGroup 7', ListTypeGroup: 'ListTypeGroup7', ListTypeGroupDescription: 'ListTypeGroupDescription 7', ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb7', __metadata: {} }, { AuthorisationGroup: 'AuthorisationGroup 8', ListTypeGroup: 'ListTypeGroup8', ListTypeGroupDescription: 'ListTypeGroupDescription 8', ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb8', __metadata: {} } ] } } ]; //This is the values which I should search find in oDataSet //The to_ListTypeGroupAssignment or other property which under the same structure //should be with the following path but under the results which is the only //hardcoded property var aProperties = [ "to_ListTypeGroupAssignment/ListTypeGroup", "to_ListTypeGroupAssignment/ListTypeGroupDescription" ] 

这是输出

这是输出的示例,它应该从上面输入中的两个对象合并构建

 var aSelectedDataSet = [ { __metadata: { aaa: 111, bbb: 222 }, to_ListTypeGroupAssignment: { results: [ { ListTypeGroup: 'ListTypeGroup1', ListTypeGroupDescription: 'ListTypeGroupDescription 1' }, { ListTypeGroup: 'ListTypeGroup2', ListTypeGroupDescription: 'ListTypeGroupDescription 2', }, { ListTypeGroup: 'ListTypeGroup3', ListTypeGroupDescription: 'ListTypeGroupDescription 3', } ] } }, { __metadata: { aaa: 333, bbb: 444 }, to_ListTypeGroupAssignment: { results: [ { ListTypeGroup: 'ListTypeGroup1', ListTypeGroupDescription: 'ListTypeGroupDescription 1' }, { ListTypeGroup: 'ListTypeGroup2', ListTypeGroupDescription: 'ListTypeGroupDescription 2', }, { ListTypeGroup: 'ListTypeGroup3', ListTypeGroupDescription: 'ListTypeGroupDescription 3', } ] } } ] 

只是为了澄清下面的评论:)唯一可以硬编码的results不是任何属性名称,如ListTypeGroup和ListTypeGroupDescription这应该是通用的,并从aProperties中读取

你看oData的结构应该如下

 property(like -> to_ListTypeGroupAssignmen) results(hardcoded & mandatory in every exist object) properties(like ListTypeGroup& ListTypeGroupDescription with there values) 

如果我需要更清楚,请让我知道如何,我应该添加哪些附加信息…这是在我尽可能更新问题后…

您可以使用这个递归的纯JavaScript函数:

下面的代码段将此函数应用于您提供的示例数据并返回所需的结果:

 function extract(data, select, curpath) { var result = {}; // Part of the path that has been traversed to get to data: curpath = curpath || ''; if (typeof data !== 'object') { // data is a primitive (we assume) return data; } if (typeof data.slice === 'function') { // data is an Array return data.map(function (el, idx) { return extract(el, select, curpath); // same path! }); } // data is an Object: // The specific case of the "__metadata" property if (data.__metadata !== undefined && curpath.length === 0) { result.__metadata = data.__metadata; } // Core of this algorithm: take the relevant paths only... var subselect = select.filter(function(path) { return (path+'/').indexOf(curpath) == 0; }); subselect.forEach(function (path, _, subselect) { // then get the next property in such path... var prop = path.substr(curpath.length).split('/')[0]; // and check if we have that property on the current object: if (data[prop] !== undefined) { // If so, recurse while adding this to the current path: result[prop] = extract(data[prop], subselect, curpath+prop+'/'); } }); // The specific case of the "results" property if (data.results !== undefined) { // recurse with same path! result.results = extract(data.results, select, curpath); } return result; } // Test data var oDataSet = [{ __metadata: { aaa: 111, bbb: 222 }, to_ExcludedTerms: {results: []}, to_ListTypeGroupAssignment: { results: [ { AuthorisationGroup: 'AuthorisationGroup 1', ListTypeGroup: 'ListTypeGroup1', ListTypeGroupDescription: 'ListTypeGroupDescription 1', ParentKey: '8ae25d47-c3cc-4ee3-a040-ea00505692111', __metadata: {} }, { AuthorisationGroup: 'AuthorisationGroup 2', ListTypeGroup: 'ListTypeGroup2', ListTypeGroupDescription: 'ListTypeGroupDescription 2', ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb7', __metadata: {} }, { AuthorisationGroup: 'AuthorisationGroup 3', ListTypeGroup: 'ListTypeGroup3', ListTypeGroupDescription: 'ListTypeGroupDescription 3', ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb5', __metadata: {} } ] } }, { __metadata: { aaa: 333, bbb: 444 }, to_ExcludedTerms: {results: []}, to_ListTypeGroupAssignment: { results: [ { AuthorisationGroup: 'AuthorisationGroup 6', ListTypeGroup: 'ListTypeGroup6', ListTypeGroupDescription: 'ListTypeGroupDescription 6', ParentKey: '8ae25d47-c3cc-4ee3-a040-ea00505692116', __metadata: {} }, { AuthorisationGroup: 'AuthorisationGroup 7', ListTypeGroup: 'ListTypeGroup7', ListTypeGroupDescription: 'ListTypeGroupDescription 7', ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb7', __metadata: {} }, { AuthorisationGroup: 'AuthorisationGroup 8', ListTypeGroup: 'ListTypeGroup8', ListTypeGroupDescription: 'ListTypeGroupDescription 8', ParentKey: '34bcdc74-ab42-4538-8657-0a2b0473fcb8', __metadata: {} } ] } } ]; var aProperties = [ "to_ListTypeGroupAssignment/ListTypeGroup", "to_ListTypeGroupAssignment/ListTypeGroupDescription" ]; // (End of sample data) // Call the function to get the result: var aSelectedDataSet = extract(oDataSet, aProperties); // For this snippet only: output the result in readable format document.write('
'+JSON.stringify(aSelectedDataSet, 0, 4)+'

');

其中一个简短的解决方案是使用lodash。 它有_.assignInWith(object, sources, [customizer])函数,使用它你将有以下内容:

 var customizer = function(key) { return key in aPropertis } var newSet = _.assignInWith({} , oDataSet, customizer) 

但是它只适用于第一级属性。

不是最优雅的方式,但有效。

JSFiddle链接

比较嵌套结构并删除不需要的键。

限制:
1. __metadata是硬编码的
2. results是硬编码的

您想要的输出与生成的输出不同,不同之处在于您的输出:

 aSelectedDataSet[2].to_ListTypeGroupAssignment.results[1].ListTypeGroupDescription === 1 

而在生成的输出中它是:

 aSelectedDataSet[2].to_ListTypeGroupAssignment.results[1].ListTypeGroupDescription === 6 

我想,这是你问题上的一个错字。

码:

 var convertPropertyRelation = function(propertiesArray) { if (!Array.isArray(propertiesArray)) return []; var formattedProperties = {}, i, len = propertiesArray.length, currentRelation; for (i = 0; i < len; i++) { currentRelation = propertiesArray[i].split('/'); if (formattedProperties.hasOwnProperty(currentRelation[0])) { formattedProperties[currentRelation[0]].push(currentRelation[1]); } else { formattedProperties[currentRelation[0]] = [currentRelation[1]]; } } return formattedProperties; }; var generateDataSet = function() { var formattedProperties = convertPropertyRelation(aProperties), firstRelation = Object.keys(formattedProperties), i, len = firstRelation.length, j, resultArray, resultLength; var dataSet = oDataSet.map(function(dataSetObject) { for (var firstKey in dataSetObject) { if (firstKey === '__metadata') { continue; } else if (firstRelation.indexOf(firstKey) === -1) { delete dataSetObject[firstKey]; } else { // if first relation is present if (dataSetObject.hasOwnProperty(firstKey)) { // results array in the firstRelation resultArray = dataSetObject[firstKey].results; // for all results for (j = 0, resultLength = resultArray.length; j < resultLength; j++) { // for all keys in current result for (var respectiveKey in resultArray[j]) { // if the key is present leave it as it is if (formattedProperties[firstKey].indexOf(respectiveKey) === -1) { delete resultArray[j][respectiveKey]; } } } } } } return dataSetObject; }); return dataSet; }; 

您必须将oDataSet的每个属性与aSelectedDataSet的每个属性进行比较

 var res=[]; for (var key1 in oDataSet){ for(var key2 in aSelectedDataSet ){ if(key1==key2){ res[key1]=oDataSet[key1]; } } } 

编辑:

如果你这样定义filter

 var filter={ __metadata:'', to_ListTypeGroupAssignment:{ results:[{ ListTypeGroup:'', ListTypeGroupDescription:'' }] } } 

并使用递归将其应用于数据

 function recursiveValue(filter,data){ var res={}; for(var key in filter){ var val=data[key]; var p=filter[key]; if(val==='undefined') continue; if(p===''){ res[key] = val; }else if(Array.isArray(p)){ var tmp = []; for(var i=0;i 

像这样

 var results=[]; for(var i=0;i 

你得到

 console.log(results); 

您可以使用ES5提供的函数式编程技术来解决这个问题。 试试这个小提琴: https : //jsfiddle.net/yh39of1b/3/

 var aProperties = [ "to_ListTypeGroupAssignment/ListTypeGroup", "to_ListTypeGroupAssignment/ListTypeGroupDescription" ]; //maps the properties you wish to capture var propertyList = aProperties.map(function(properties) { return properties.split('/'); }); //reduces the oData array to the data you require aSelectedDataSet = oData.reduce(function(existing,current){ var obj = {}; //each iteration of oData goes through each property group //first at the parent property level propertyList.forEach(function(property){ if (typeof obj[property[0]] === 'undefined') { obj[property[0]] = {}; obj[property[0]].results = []; } if(current[property[0]]) { //now at the child property level current[property[0]].results.forEach(function(result,index){ if(typeof obj[property[0]].results[index] === 'undefined') obj[property[0]].results[index] = {}; obj[property[0]].results[index][property[1]] = result[property[1]]; }); } }); //add the newly mapped object to the aSelectedDataSet array existing.push(obj); return existing; },[]);