Jump to content

Recommended Posts

BACKGROUND:  I recently discovered the following piece of code on StackOverflow,.  Although it works for a single property comparison, I do not understand it well enough to expand it to cope with multiple properties.

function getUnique(inputArr, comp) {
  const unique = inputArr.map(e => e[comp]).map((e, i, final) => final.indexOf(e) === i && i).filter(e => inputArr[e]).map(e => inputArr[e]);
  return unique;
}

I would like to create a function that would permit the comparison of multiple values on the order of

function getUnique(inputArr, comp1 [, comp2[, comp3 [...]]]){...}

Any suggestions?

At minimum could you help with a better understanding of how it does what it does.  It maps and filters, but in a manner that I do not comprehend easily enough to manipulate.

Roddy

PS.  A little experimentation came up with the following solution.

function getUnique(inputArr, comp1, comp2) {
	const unique = inputArr.map(e => e[comp1] && e[comp2])
      .map((e, i, final) => final.indexOf(e) === i && i)
      .filter(e => inputArr[e])
      .map(e => inputArr[e]);
	return unique;
}

It achieves my goal, but a little more understanding is still requested.

 

Edited by iwato
Solution Provided

Share this post


Link to post
Share on other sites

Here's a version if  you're not into the whole brevity thing:


function getUnique(inputArr, comp) {
  const unique = inputArr.map(function (e) {
    
    // return an array of only one property from the original array of objects (if defined)
    console.log(e[comp]);
    return e[comp]; 
  
  }).map(function (e, i, final) {
    
    console.log("final", final);
    console.log("e", e);
    console.log("i", i);
    // return an array of either false values or indexes
    // this will result in an array where each value is listed only once, in the first position it appears,
    // and any other appearances will be false
    // the array will be the same length
    return final.indexOf(e) === i && i;

  }).filter(function (e) {
    
    console.log("e", e);
    console.log(inputArr[e]);
    // this will create an array of objects from the original array in each index from the previously mapped temp array
    // this will exclude the duplicates because those indexes in the previous array are set to false
    return inputArr[e]; 

  }).map(function (e) {
    
    console.log("e", e);
    console.log(inputArr[e]);
    // this will reindex the array to remove "holes"
    return inputArr[e]; 

  });

  console.log(unique);
  return unique;
}

var ar = [
  {
    'prop': 1
  },
  {
    'prop': 2
  },
  {
    'prop': 1
  },
  {
    'prop': 3
  },
  {
    'prop': 1
  },
  {
    'prop': 4
  },
  {
    'prop2': 1
  },
  {
    'prop3': 1
  }
];

getUnique(ar, 'prop');

I would like to create a function that would permit the comparison of multiple values on the order of

What's the purpose?  This function takes an array of objects, and will return an array of those objects that have unique values for a particular property.  How do multiple values fit into that?  Do you have an example?

  • Like 1

Share this post


Link to post
Share on other sites

I have erred.  What worked for objects with three properties does not work for objects with two properties.  I had hoped that my modification would have rendered the following transformation, but it does not.

Input Array
Object { visitorID: "6b77f74d969f0254", fullDate: "2019/01/01" }
Object { visitorID: "6b77f74d969f0254", fullDate: "2019/01/01" }
Object { visitorID: "8305d1d7c98cfe07", fullDate: "2019/01/03" }
Object { visitorID: "8305d1d7c98cfe07", fullDate: "2019/01/03" }
Object { visitorID: "8305d1d7c98cfe07", fullDate: "2019/01/03" }
Object { visitorID: "8305d1d7c98cfe07", fullDate: "2019/01/03" }
Object { visitorID: "8305d1d7c98cfe07", fullDate: "2019/01/04" }
Object { visitorID: "470b11ecb96f51a8", fullDate: "2019/01/04" }
Object { visitorID: "470b11ecb96f51a8", fullDate: "2019/01/05" }
Object { visitorID: "7783172ce39cd663", fullDate: "2019/01/05" }

Output Array
Object { visitorID: "6b77f74d969f0254", fullDate: "2019/01/01" }
Object { visitorID: "8305d1d7c98cfe07", fullDate: "2019/01/03" }
Object { visitorID: "8305d1d7c98cfe07", fullDate: "2019/01/04" }
Object { visitorID: "470b11ecb96f51a8", fullDate: "2019/01/04" }
Object { visitorID: "470b11ecb96f51a8", fullDate: "2019/01/05" }
Object { visitorID: "7783172ce39cd663", fullDate: "2019/01/05" }

I expected the above transformation base on the below transformation

var dataArr = [
	{"name":"Steven Smith","country":"England","age":35},
	{"name":"Hannah Reed","country":"Scottland","age":23},
	{"name":"Steven Smith","country":"England","age":35},
	{"name":"Robert Landley","country":"England","age":84},
	{"name":"Steven Smith","country":"England","age":35},
	{"name":"Robert Landley","country":"England","age":56}
];

var output = [
	{"name":"Steven Smith","country":"England","age":35},
	{"name":"Hannah Reed","country":"Scottland","age":23},
	{"name":"Robert Landley","country":"England","age":84},
	{"name":"Robert Landley","country":"England","age":56}
];

In both cases I used two variables for comparison.  In the first case, however, there were only two variables to compare.  In the second there was a third variable for which no matching was intended.

Alas, where have I gone wrong?

Roddy

 

 

 

Share this post


Link to post
Share on other sites

Thank you, SVG, for your explanation of the one property-value pair reduction.  My transformation of the one property-value pair reduction into a dual property-value pair reduction works for objects with three properties, but not two.  Can you explain why?

Roddy

Share this post


Link to post
Share on other sites

Are you referring to code that was edited into your first post?

Share this post


Link to post
Share on other sites

Yes!

Share this post


Link to post
Share on other sites

Add output statements similar to what I have, you should see why it's not comparing things the way you expect.

Share this post


Link to post
Share on other sites

The Data

var visitData = [
	{'visitorID':'6b77f74d969f0254','fullDate':'2019/01/01'},
	{'visitorID':'6b77f74d969f0254','fullDate':'2019/01/01'},
	{'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/03'},
	{'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/03'},
	{'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/03'},
	{'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/03'},
	{'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/04'},
	{'visitorID':'470b11ecb96f51a8','fullDate':'2019/01/04'},
	{'visitorID':'470b11ecb96f51a8','fullDate':'2019/01/05'},
	{'visitorID':'7783172ce39cd663','fullDate':'2019/01/05'},
	{'visitorID':'1834494d8537012d','fullDate':'2019/01/06'},
	{'visitorID':'3321037b66164959','fullDate':'2019/01/06'}
];

Alright, I have played with the map function and discovered that the following code displays exactly what I want -- a subset of unique objects.

Simply I do not know how to convert it into anything useful.

The Code

function getUniqAnalysis(inputArr, comp1, comp2) {
  const unique = inputArr.map(function(e) {
    console.log('e[comp1]: ' + e[comp1] + ' e[comp2]: ' + e[comp2]);
  });
}

Something Useful

var somethingUseful = [
{'visitorID':'6b77f74d969f0254','fullDate':'2019/01/01'},
{'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/03'},
{'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/04'},
{'visitorID':'470b11ecb96f51a8','fullDate':'2019/01/04'},
{'visitorID':'470b11ecb96f51a8','fullDate':'2019/01/05'},
{'visitorID':'7783172ce39cd663','fullDate':'2019/01/05'},
{'visitorID':'1834494d8537012d','fullDate':'2019/01/06'},
{'visitorID':'3321037b66164959','fullDate':'2019/01/06'}
];

Please advise.

Roddy

 

 

Share this post


Link to post
Share on other sites

This seemed to me to be an easier solution to your problem.
Check the reference links for further information or look up the new Set() function of ES6

	<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width-device-width,initial-scale=1.0, user-scalable=yes"/>
<title> Unique Object Entries </title>
<!-- From: http://w3schools.invisionzone.com/topic/59291-eliminating-objects-of-an-array/ -->
</head>
<body>
	<script>
var visitData = [
   {'visitorID':'6b77f74d969f0254','fullDate':'2019/01/01'},
   {'visitorID':'6b77f74d969f0254','fullDate':'2019/01/01'},
   {'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/03'},
   {'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/03'},
   {'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/03'},
   {'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/03'},
   {'visitorID':'8305d1d7c98cfe07','fullDate':'2019/01/04'},
   {'visitorID':'470b11ecb96f51a8','fullDate':'2019/01/04'},
   {'visitorID':'470b11ecb96f51a8','fullDate':'2019/01/05'},
   {'visitorID':'7783172ce39cd663','fullDate':'2019/01/05'},
   {'visitorID':'1834494d8537012d','fullDate':'2019/01/06'},
   {'visitorID':'3321037b66164959','fullDate':'2019/01/06'}
];
	/* Following solution from:
  https://stackoverflow.com/questions/36032179/remove-duplicates-in-an-object-array-javascript
*/
var uniq = new Set(visitData.map(e => JSON.stringify(e)));
var res = Array.from(uniq).map(e => JSON.parse(e));
console.log(JSON.stringify(res));
	</script>
</body>
</html>
	

 

  • Like 1

Share this post


Link to post
Share on other sites

Thank you, JMRKER, for your input.

The problem was finally resolved using the following .filter( ) function.

var uniqVals = visitData.filter((obj, index, self) =>
  index === self.findIndex((other) => (
    other.visitorID === obj.visitorID && other.fullDate === obj.fullDate 
  ))
);

Roddy

Share this post


Link to post
Share on other sites

You almost had it with your changed code, it's just that e[comp1] && e[comp2] doesn't do what you expect or intended.

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...

×
×
  • Create New...