簡體   English   中英

如何匹配兩個對象之間的值並使用特定值創建新對象

[英]How to match values between two objects and create new with specific values

我有對象oDataSetaProperties對象的數組,我想匹配在aPropertisoDataSet中找到的相同值,並創建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('<pre>'+JSON.stringify(aSelectedDataSet, 0, 4)+'</pre>');

算法說明:

代碼已注釋。 這是算法的工作原理:

  • 該函數是遞歸的並采用當前數據,一旦該函數被遞歸調用,它就只是原始數據的一個子部分。
  • 該函數還采用路徑樣式屬性進行選擇。 此外,這個列表會更短,因為函數被遞歸調用,所以它只有那些仍然與數據部分相關的條目。
  • 第三個參數是已經遍歷過的路徑。 在最初的調用中,這只是一個空字符串,但隨着遞歸的進行,它將變成 'to_ListTypeGroupAssignment/',然后甚至是 'to_ListTypeGroupAssignment/ListTypeGroup/'(總是帶有終止斜杠)。
  • 該函數的每次調用都將返回與(路徑樣式)選擇匹配的給定數據的一部分。
  • 該函數首先識別數據的類型:它是原始值(字符串、數字、布爾值)還是數組(初始調用時就是這種情況),還是(非數組)對象。
  • 如果它是一個數組,則只為每個元素遞歸調用該函數,而不向路徑添加任何內容。 然后將每次調用的結果存儲在一個數組中,該數組成為返回值。
  • 如果是原始值,則表示我們遞歸到“樹”中的“葉子”。 既然我們到了這里,我們可以假設“路徑”一直匹配到這一點,因此必須返回原始值,以便將其添加到結果中
  • 它是一個對象,遍歷選擇路徑以查看這些路徑中的下一級是否與當前數據的對象屬性匹配。 如果是這樣,該屬性值將通過遞歸調用傳遞,同時還將那段路徑添加到“當前”路徑

__metadataresults顯然有例外,它們在代碼中分開處理。

您必須將 oDataSet 的每個屬性與 aSelectedDataSet 的每個屬性進行比較

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

編輯:

如果你像這樣定義過濾器

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<val.length;i++){
                tmp.push(recursiveValue(filter[key][0],val[i]));
            }
            res[key] = tmp;
        }else if(typeof p=='object'){
            res[key] = recursiveValue(filter[key],val);
        }
    }
    return res;
}

像這樣

var results=[];
for(var i=0;i<oDataSet.length;i++){
    results.push(recursiveValue(filter,oDataSet[i]));
}

你得到

console.log(results);

一種簡短的解決方案是使用 lodash。 它具有_.assignInWith(object, sources, [customizer])功能,使用它您將獲得以下內容:

var customizer = function(key) { return key in aPropertis }

var newSet = _.assignInWith({} , oDataSet, customizer)

但是,它僅適用於第一級屬性。

您可以使用 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;
},[]);

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

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;
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM