简体   繁体   English

遍历对象数组并根据属性添加它们

[英]Loop through array of objects and add them based on a property

I have an array with objects like below. 我有一个对象如下的数组。

0:Object
 BARKOD:"Pa Detatime"
 DETAJIM1:""
 DETAJIM2:""
 DTMODIFIKIM:"2017-10-02T16:06:53.206Z"
 KODARTIKULLI:"SD13137"
 KODI:"MX02"
 KODNJESIA1:"cope"
 PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56"
 cmimibaze:0
 gjendje:1
1:Object
 BARKOD:"Pa Detatime"
 DETAJIM1:""
 DETAJIM2:""
 DTMODIFIKIM:"2017-10-02T16:06:53.206Z"
 KODARTIKULLI:"SD13137"
 KODI:"MX02"
 KODNJESIA1:"cope"
 PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56"
 cmimibaze:0
 gjendje:1
2:Object
 BARKOD:"Pa Detatime"
 DETAJIM1:""
 DETAJIM2:""
 DTMODIFIKIM:"2017-10-02T16:06:53.206Z"
 KODARTIKULLI:"SD13137"
 KODI:"MX03"
 KODNJESIA1:"cope"
 PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56"
 cmimibaze:0
 gjendje:1
3:Object
 BARKOD:"Pa Detatime"
 DETAJIM1:""
 DETAJIM2:""
 DTMODIFIKIM:"2017-10-02T16:06:53.206Z"
 KODARTIKULLI:"SD13141"
 KODI:"MX02"
 KODNJESIA1:"cope"
 PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56"
 cmimibaze:0
 gjendje:1

Now I want to remove the duplicates using these 2 properties: "KODI" and "KODARTIKULLI" , for example at the first 2 objects you can see that both "KODI" and "KODARTIKULLI" are the same so I want to keep only one. 现在,我想使用以下两个属性删除重复项: "KODI""KODARTIKULLI" ,例如,在前两个对象中,您可以看到"KODI""KODARTIKULLI"都相同,因此我只想保留一个。

And the second question which is more important and may even solve the first one. 第二个问题更重要,甚至可以解决第一个问题。 These objects are products that are taken from different storage units, ("KODI" represents the storage unit id). 这些对象是取自不同存储单元的产品(“ KODI”表示存储单元ID)。 So what I want is for a unique product (product id is "KODARTIKULLI") to add all the available units (available units are stored in "gjendje"). 因此,我想要的是一个独特的产品(产品ID为“ KODARTIKULLI”)来添加所有可用单位(可用单位存储在“ gjendje”中)。 This may seem a bit complicated but i want that the above array to look like below: 这似乎有点复杂,但是我希望上面的数组看起来像下面这样:

0:Object
 BARKOD:"Pa Detatime"
 DETAJIM1:""
 DETAJIM2:""
 DTMODIFIKIM:"2017-10-02T16:06:53.206Z"
 KODARTIKULLI:"SD13137"
 KODI:"MX02"
 KODNJESIA1:"cope"
 PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56"
 cmimibaze:0
 gjendje:2
1:Object
 BARKOD:"Pa Detatime"
 DETAJIM1:""
 DETAJIM2:""
 DTMODIFIKIM:"2017-10-02T16:06:53.206Z"
 KODARTIKULLI:"SD13141"
 KODI:"MX02"
 KODNJESIA1:"cope"
 PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56"
 cmimibaze:0
 gjendje:1

So since the first 2 objects are the same product and come from the same storage unit, to just keep one. 因此,由于前两个对象是同一产品且来自同一存储单元,因此只需保留一个对象。 And the second and third objects are still the same product but come from different storage units, so in this case just add "gjendje" . 第二个和第三个对象仍然是相同的产品,但是来自不同的存储单元,因此在这种情况下,只需添加"gjendje" In the end there should be just one product with KODARTIKULLI:"SD13137" and "gjendje:2" ( gjendje:1+gjendje:1=gjendje:2 ). 最后,应该只有一个带有KODARTIKULLI:"SD13137"产品KODARTIKULLI:"SD13137""gjendje:2"gjendje:1+gjendje:1=gjendje:2 )。 The same for products with different "KODARTIKULLI" . 具有不同"KODARTIKULLI"产品"KODARTIKULLI"

What I've tried: I can remove duplicates based on one property but not using 2 properties: 我尝试过的操作:我可以基于一个属性删除重复项,但不能使用2个属性:

// Remove duplicates of it's own, ex: only keeps one unique object based on KODARTIKULL
function removeDuplicates(originalArray, prop) {
     var newArray = [];
     var lookupObject  = {};

     for(var i in originalArray) {
        lookupObject[originalArray[i][prop]] = originalArray[i];
     }

     for(i in lookupObject) {
         newArray.push(lookupObject[i]);
     }
      return newArray;
 }

I can call this twice for both "KODARTIKULLI" and "KODI" but that won't work because it will just keep removing products not based on my conditions. 我可以为"KODARTIKULLI""KODI"两次调用此"KODARTIKULLI" ,但这将不起作用,因为它只会根据我的条件继续移除产品。

I also tried to add "gjendje" by looping through the whole array. 我还尝试通过遍历整个数组来添加"gjendje" So for each product I'll add the "gjendje" from all the other products with the same "KODARTIKULLI" . 因此,对于每种产品,我将使用相同的"gjendje"在所有其他产品中添加"KODARTIKULLI" After this then I'd call the above function and since all the same products would have the same "gjendje" , I'd just remove all the duplicates. 之后,我将调用上面的函数,并且由于所有相同的产品都具有相同的"gjendje" ,因此我将删除所有重复项。 But this also doesn't work because there are some products that come from the same storage unit which need to just be removed because are exactly the same. 但这也不起作用,因为有些产品是来自同一存储单元的,因为它们是完全相同的,因此只需要删除它们即可。

  // Loop through all objects in the array
  for (var i = 0; i < newArrMagGjendje.length; i++) {

    // Loop through all of the objects beyond i
    // Don't increment automatically; we will do this later
    for (var j = i+1; j < newArrMagGjendje.length;j++ ) {

      // Check if our x values are a match
      if (newArrMagGjendje[i].KODARTIKULLI == newArrMagGjendje[j].KODARTIKULLI) {
        newArrMagGjendje[i].gjendje=newArrMagGjendje[i].gjendje+newArrMagGjendje[j].gjendje;
        newArrayM.push( newArrMagGjendje[i]);
      } 
    }
  }

I know it looks a bit long, but I'm stuck at the moment and didn't know how to explain it differently. 我知道它看起来有点长,但是我现在还停留在上面,不知道如何用不同的方式解释它。 Thank you 谢谢

function removeDuplicates(arr) {
    console.log("original length: "+arr.length);
    for (var i=0; i<arr.length; i++) {
        var listI = arr[i];
        loopJ: for (var j=0; j<arr.length; j++) {
            var listJ = arr[j];
            if (listI === listJ) continue; //Ignore itself
            for (var k=listJ.length; k>=0; k--) {
                if (JSON.stringify(listJ[k]) !== JSON.stringify(listI[k])) continue loopJ;
            }// At this point, their values are equal.

            arr.splice(j--, 1);
        }
    }
    console.log("length without duplicates: "+arr.length);
    return arr;
}

This is a function I wrote a little while back to remove any duplicate objects in an array. 这是我不久前写的一项函数,用于删除数组中的所有重复对象。 Since you want to apply only to two attributes then all we need to do is remove the 3rd loop and just check those two attributes instead. 由于您只想应用两个属性,因此我们要做的就是删除第3个循环,而只需检查这两个属性即可。

Also note, there are better ways to compare objects than JSON.stringify but efficiency wasn't needed for me, I don't know if that's the case for you. 还请注意,比JSON.stringify更好的方法来比较对象,但是我不需要效率,我不知道您是否需要这种方法。

Modified code for your purposes: 修改后的代码供您使用:

function removeDuplicates(arr) {
    console.log("original length: "+arr.length);
    for (var i=0; i<arr.length; i++) {
        var listI = arr[i];
        loopJ: for (var j=0; j<arr.length; j++) {
            var listJ = arr[j];
            if (listI === listJ) continue; //Ignore itself
            if (JSON.stringify(listJ.KODI) !== JSON.stringify(listI.KODI)) {
                continue loopJ;
            }
            if (JSON.stringify(listJ.KODNJESIA1) !== JSON.stringify(listI.KODNJESIA1)) {
                continue loopJ;
            }      
            arr.splice(j--, 1);
        }
    }
    console.log("length without duplicates: "+arr.length);
    return arr;
}

I hope this is what you were looking for 我希望这就是你想要的

A simple way to filter based on 2 properties is to create a temporary hash object that uses the combined values of those 2 properties as keys. 一种基于2个属性进行过滤的简单方法是创建一个临时哈希对象,该对象使用这2个属性的组合值作为键。

 var data = [{ key1: 'A', key2: 1 }, { key1: 'A', key2: 1 }, { key1: 'B', key2: 1 }]; var tmp = {}; var res = data.filter(function(item) { // use a separator for the values to prevent possible collisions and prevent adding numbers var combined = item.key1 + '|' + item.key2, isUnique = !tmp[combined]; if (isUnique) { tmp[combined] = true; } return isUnique; }); console.log(res) 

The second part of the question is a bit unclear 问题的第二部分有点不清楚

I think you are looking for array.prototype.reduce , that will allow you to apply a callback function to your array to output a new array matching the functions output criteria. 我认为您正在寻找array.prototype.reduce ,这将允许您将回调函数应用于数组,以输出匹配函数输出条件的新数组。

As an aside, please read up on how to provide a minimal example if you have an array of objects it helps to have an actual array of objects and not a string that needs to be converted in order to create a working example. 顺便说一句,如果您有一个对象数组,请继续阅读如何提供一个最小的示例 ,这将有助于拥有一个实际的对象数组,而不是一个需要转换以创建工作示例的字符串。

Edit 编辑

Added a second reducer to total the gjendje key on matched Kodartikulli keys, you could do this with one reducer, but ( personal opinion ) I think it is generally a better practice to keep your functions narrow in scope. 为匹配的Kodartikulli键上的gjendje键添加了第二个reducer,您可以使用一个reducer来做到这一点,但是( 个人观点 )我认为通常最好的做法是使函数范围缩小。

 const data = [ { BARKOD:"Pa Detatime", DETAJIM1:"", DETAJIM2:"", DTMODIFIKIM:"2017-10-02T16:06:53.206Z", KODARTIKULLI:"SD13137", KODI:"MX02", KODNJESIA1:"cope", PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56", cmimibaze:0, gjendje:1, }, { BARKOD:"Pa Detatime", DETAJIM1:"", DETAJIM2:"", DTMODIFIKIM:"2017-10-02T16:06:53.206Z", KODARTIKULLI:"SD13137", KODI:"MX02", KODNJESIA1:"cope", PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56", cmimibaze:0, gjendje:1, }, { BARKOD:"Pa Detatime", DETAJIM1:"", DETAJIM2:"", DTMODIFIKIM:"2017-10-02T16:06:53.206Z", KODARTIKULLI:"SD13137", KODI:"MX03", KODNJESIA1:"cope", PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56", cmimibaze:0, gjendje:1, }, { BARKOD:"Pa Detatime", DETAJIM1:"", DETAJIM2:"", DTMODIFIKIM:"2017-10-02T16:06:53.206Z", KODARTIKULLI:"SD13141", KODI:"MX02", KODNJESIA1:"cope", PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56", cmimibaze:0, gjendje:1, } ]; const dedupe = (group, current) => { const index = group.findIndex(val => (val.KODI == current.KODI && val.KODARTIKULLI == current.KODARTIKULLI)); if (index === -1) { group.push(current); } return group; }; const totals = (group, current) => { const index = group.findIndex(val => val.KODARTIKULLI == current.KODARTIKULLI); if (index === -1) { return [ ...group, current]; } group[index].gjendje += current.gjendje; return group; }; const result = data.reduce(dedupe, []).reduce(totals, []); console.log(result); 

First get unique record based on KODARTIKULLI and add the storage units to that unique record. 首先获取基于KODARTIKULLI的唯一记录,然后将存储单元添加到该唯一记录。

var array = [{
 BARKOD:"Pa Detatime",
 DETAJIM1:"",
 DETAJIM2:"",
 DTMODIFIKIM:"2017-10-02T16:06:53.206Z",
 KODARTIKULLI:"SD13137",
 KODI:"MX02",
 KODNJESIA1:"cope",
 PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56",
 cmimibaze:0,
 gjendje:1,
 },{
 BARKOD:"Pa Detatime",
 DETAJIM1:"",
 DETAJIM2:"",
 DTMODIFIKIM:"2017-10-02T16:06:53.206Z",
 KODARTIKULLI:"SD13137",
 KODI:"MX02",
 KODNJESIA1:"cope",
 PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56",
 cmimibaze:0,
 gjendje:1
 },{
 BARKOD:"Pa Detatime",
 DETAJIM1:"",
 DETAJIM2:"",
 DTMODIFIKIM:"2017-10-02T16:06:53.206Z",
 KODARTIKULLI:"SD13137",
 KODI:"MX03",
 KODNJESIA1:"cope",
 PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56",
 cmimibaze:0,
 gjendje:1
 },
 {
 BARKOD:"Pa Detatime",
 DETAJIM1:"",
 DETAJIM2:"",
 DTMODIFIKIM:"2017-10-02T16:06:53.206Z",
 KODARTIKULLI:"SD13141",
 KODI:"MX02",
 KODNJESIA1:"cope",
 PERSHKRIMARTIKULLI:"Emporio Armani 4097 5574 71 56",
 cmimibaze:0,
 gjendje:1
}];

Here added new property to storage all the KODI info as array 此处添加了新属性以将所有KODI信息存储为数组

function addStorage(arr,hash,index,sd){
 var item = hash[index];
  if(item.SD.indexOf(sd) === -1){
    item.SD.push(sd);
  }
  arr[item.index].StorageUnit = item.SD;
  arr[item.index].gjendje = item.SD.length;
}

getUnique method will remove the duplicate based on KODARTIKULLI and add record with different store to unique record getUnique方法将删除基于KODARTIKULLI的重复项,并将具有不同存储的记录添加到唯一记录

function getUnique(arr) {
  var hash = [];
  var storageHash = [];
  var length = arr.length,index = 0;
  for (; index < length;) {
    var item = arr[index];
    var key = item.KODARTIKULLI;    
    if (hash[key] !== undefined)
    {      
      addStorage(arr,hash,key,item.KODI);
      arr.splice(index, 1);
      index--;
      length--;
    } else {      
      hash[key] = {
         index:index,
         SD:[item.KODI]
      }
    }
    index++;
  }
  return arr;
}
console.log(getUnique(array));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM