Home > database >  How to calculate difference of two arrays with same value at second position
How to calculate difference of two arrays with same value at second position

Time:04-25

I've got a git diff output string parsed to this array, which gives me all changed dependencies in a package.json file:

const data = [
    [ '-', '@date-io/moment', '1.3.13', '1', '3', '13' ],
    [ ' ', '@date-io/moment', '1.3.14', '1', '3', '14' ],
    [ '-', '@emotion/react', '11.7.0', '11', '7', '0' ],
    [ '-', '@emotion/styled', '11.6.0', '11', '6', '0' ],
    [ ' ', '@emotion/react', '11.8.2', '11', '8', '2' ],
    [ ' ', '@emotion/styled', '11.8.1', '11', '8', '1' ]
]

The first element ( / -) shows me if this change was added or deleted. The second element is the package name (this is the element, which connects two arrays), and the next fields give me the version. Now I need to iterate this array to find out which kind of version change has been made for each package. So the output should be:

{
    '@date-io/moment': 'patch',
    '@emotion/react': 'minor',
    '@emotion/styled': 'minor'
}

I tried to get all packages by doing

const result = {}
data.forEach(d => {
    result[d[1]] = bump // how to calculate `bump`?
})

But this doesn't handle and - and it doesn't calculate the type of version bump.

CodePudding user response:

Using Array.prototype.reduce to reduce you can reduce the array into an object and for each package use Array.prototype.find to find the corresponding change. Then you can compare the versions and determine its change.

const data = [
    [ '-', '@date-io/moment', '1.3.13', '1', '3', '13' ],
    [ ' ', '@date-io/moment', '1.3.14', '1', '3', '14' ],
    [ '-', '@emotion/react', '11.7.0', '11', '7', '0' ],
    [ '-', '@emotion/styled', '11.6.0', '11', '6', '0' ],
    [ ' ', '@emotion/react', '11.8.2', '11', '8', '2' ],
    [ ' ', '@emotion/styled', '11.8.1', '11', '8', '1' ]
];

const changes = data.reduce((t, [type, name, , major, minor, patch], i, arr) => {
    if (type === " ") {
        const match = arr
          .find(([type, pName]) => type === "-" && pName === name);
        if (!match) {
          return t; // handle no match here
        }
        const [, , , pMajor, pMinor, pPatch] = match;
        return {
            ...t,
            [name]: pMajor !== major ? "major" :
                pMinor !== minor ? "minor" :
                "patch"
        }
    }
    return t;
}, {});

console.log(changes);

CodePudding user response:

  • Create a Map of all subtractions
  • Loop over all the additions and reduce it to the desired object using the map.

const data = [
  ["-", "@date-io/moment", "1.3.13", "1", "3", "13"],
  [" ", "@date-io/moment", "1.3.14", "1", "3", "14"],
  ["-", "@emotion/react", "11.7.0", "11", "7", "0"],
  ["-", "@emotion/styled", "11.6.0", "11", "6", "0"],
  [" ", "@emotion/react", "11.8.2", "11", "8", "2"],
  [" ", "@emotion/styled", "11.8.1", "11", "8", "1"],
];

const subMap = new Map(data.filter((d) => d[0] === "-").map((d) => [d[1], d]));

const additions = data.filter((d) => d[0] === " ");

const updates = additions.reduce((updates, addition) => {
  const pkgName = addition[1];
  const [maj, min, patch] = addition.slice(-3);
  const [oldMaj, oldMin, oldPatch] = subMap.get(pkgName).slice(-3);

  if (maj === oldMaj && min === oldMin && patch >= oldPatch) {
    updates[pkgName] = "patch";
  } else if (maj === oldMaj && min >= oldMin) {
    updates[pkgName] = "minor";
  } else {
    updates[pkgName] = "major";
  }

  return updates;
}, {});

console.log(updates);

CodePudding user response:

first let seperate both and - in two differnt object like this

let added={},removed={};
for(let i=0;i<data.length;i  ){
   if(data[i][0]=='-'){
     removed[data[i][1]]={
      version:data[i][2],
       major:data[i][3],
      min:data[i][4],
       patch:data[i][5]
    }
  }else{
  added[data[i][1]]={
  version:data[i][2],
  major:data[i][3],
  min:data[i][4],
  patch:data[i][5]
     }
  }
}

then create a function get diff string as follow

function getPackageChanges(ad,rm){
 if(ad.major!==rm.major) return "major";
 if(ad.min!==rm.min) return "minor";
 if(ad.patch!==rm.patch)return "patch";
 return "unknown";
}

then you can map added to this way from its key to get the resulting string

let res={};
Object.keys(added).forEach(t=>{

if(removed[t]!==undefined){
  res[t]=getPackageChanges(removed[t],added[t])
}

})

const data = [
    [ '-', '@date-io/moment', '1.3.13', '1', '3', '13' ],
    [ ' ', '@date-io/moment', '1.3.14', '1', '3', '14' ],
    [ '-', '@emotion/react', '11.7.0', '11', '7', '0' ],
    [ '-', '@emotion/styled', '11.6.0', '11', '6', '0' ],
    [ ' ', '@emotion/react', '11.8.2', '11', '8', '2' ],
    [ ' ', '@emotion/styled', '11.8.1', '11', '8', '1' ]
]


    let added={},removed={};
    for(let i=0;i<data.length;i  ){
       if(data[i][0]=='-'){
         removed[data[i][1]]={
          version:data[i][2],
           major:data[i][3],
          min:data[i][4],
           patch:data[i][5]
        }
      }else{
      added[data[i][1]]={
      version:data[i][2],
      major:data[i][3],
      min:data[i][4],
      patch:data[i][5]
         }
      }
    }

    function getPackageChanges(ad,rm){
     if(ad.major!==rm.major) return "major";
     if(ad.min!==rm.min) return "minor";
     if(ad.patch!==rm.patch)return "patch";
     return "unknown";
    }


    let res ={};
    Object.keys(added).forEach(t=>{

    if(removed[t]!==undefined){
      res[t]=getPackageChanges(removed[t],added[t])
    }

    })
console.log("result",res)

  • Related