21

I have the following array:

var tst = 
[
 {"topicId":1,"subTopicId":1,"topicName":"a","subTopicName":"w"},
 {"topicId":1,"subTopicId":2,"topicName":"b","subTopicName":"x"},
 {"topicId":1,"subTopicId":3,"topicName":"c","subTopicName":"y"},
 {"topicId":2,"subTopicId":4,"topicName":"c","subTopicName":"z"}
]

Is there an easy way that I can map that to this kind of array where topicId > id and topicName > name:

var t = 
[
  {"id":1,"name":"a"},
  {"id":2,"name":"c"}
]

I am using a modern browser and I also have _lodash if that helps. Note that there will be about 100 rows in the tst array so I don't need a very optimized solution. A simple and easy to maintain solution would be more important.

3
  • Duplicate of stackoverflow.com/questions/14446511/… Commented Jan 28, 2014 at 19:02
  • Wow I just looked at that link. Very much code. I wonder if there is a simpler lodash solution.
    – user1943020
    Commented Jan 28, 2014 at 19:05
  • what do you mean by "topicId > id and topicName > name". topicName and name are string and cannot be greater than or less than one another..?
    – xspydr
    Commented Jan 28, 2014 at 21:04

3 Answers 3

33

MOST RECENT

_.uniqBy is now preferable

Full working example here

var tst = [
 {"topicId":1,"subTopicId":1,"topicName":"a","subTopicName1":"w"},
 {"topicId":2,"subTopicId":2,"topicName":"b","subTopicName2":"x"},
 {"topicId":3,"subTopicId":3,"topicName":"c","subTopicName3":"y"},
 {"topicId":1,"subTopicId":4,"topicName":"c","subTopicName4":"z"}
];

var result = _.map(_.uniqBy(tst, 'topicId'), function (item) {
    return {
        id: item.topicId,
        name: item.topicName
    };  
});

console.log(result);

LEGACY

http://lodash.com/docs#uniq is a good start

_.uniq([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');

Your code would look like this to get topics unique by id

var t = _.uniq(tst, 'topicId');

EDIT

I made a jsfiddle

http://jsfiddle.net/q5HNw/

UPDATE

Removed unnecessary uniqueness of names

http://jsfiddle.net/q5HNw/1/

5
  • can you give me an example using the code I have. I am not quite sure how I could change the field names when I look at your example.
    – user1943020
    Commented Jan 28, 2014 at 19:06
  • The topicName is ALWAYS the same for each topicID. So could this be made more simple with just one _.uniq check ?
    – user1943020
    Commented Jan 28, 2014 at 19:33
  • Yes, just throw away the instruction with _.uniq(t, 'name'), I'll update my answer and the jsfiddle
    – axelduch
    Commented Jan 28, 2014 at 19:36
  • This failed to recognize unique topic names? At least my test failed.
    – Dalorzo
    Commented Jan 28, 2014 at 19:47
  • @Melina I think I misunderstood your point, you must use uniq to filter by topicName, because a topic with an id X and a name Y could have an id W but a name Y too
    – axelduch
    Commented Jan 28, 2014 at 19:54
2

I am one of those guys that use native functions :)

var results = tst.reduce(function(res,topic){
var exists = res.some(function(t){ return (t.id === topic.topicId && t.name === topic.topicName);});        
     if (!exists){
        res.push({"id": topic.topicId, "name": topic.topicName});
     }
return res; },[]);

Lodash version

I am not an expert using lodash, probably I will try something like this:

var results = _.reduce(tst, function(res, topic){       
    var exists = _.findIndex(res, function(t){
        return (t.id === topic.topicId && t.name === topic.topicName);
    });
    if (exists === -1){
      res.push({"id": topic.topicId, "name": topic.topicName});
    }
    return res; 
},[]);
2
  • But I already have lodash used for other things. I am wondering if this would be easier given the small number of records I have and the fact this is not needed frequently. Just thinking it might be easier to maintain with lodash.
    – user1943020
    Commented Jan 28, 2014 at 19:16
  • @Melina I translated to the original post to lodash
    – Dalorzo
    Commented Jan 28, 2014 at 19:58
-1

Using ECMAScript 2015 Array.prototype.find()

The find() method returns the value of the first element in the array that satisfies the provided testing function. Otherwise undefined is returned.

let tst = [
     {"topicId":1,"subTopicId":1,"topicName":"a","subTopicName":"w"},
     {"topicId":1,"subTopicId":2,"topicName":"b","subTopicName":"x"},
     {"topicId":1,"subTopicId":3,"topicName":"c","subTopicName":"y"},
     {"topicId":2,"subTopicId":4,"topicName":"c","subTopicName":"z"},
];

let t = [];
tst.forEach(obj => {
  // Check if the id already exists in the array 't'
  if (!t.find((self) => self.id === obj.topicId)) {
    // If not, pushes obj to t
    t.push({
      id: obj.topicId,
      name: obj.topicName
    });
  }
});

console.log(t);

You can also compare more than one property:

let tst = [
         {"topicId":1,"subTopicId":1,"topicName":"a","subTopicName":"w"},
         {"topicId":1,"subTopicId":2,"topicName":"b","subTopicName":"x"},
         {"topicId":1,"subTopicId":3,"topicName":"c","subTopicName":"y"},
         {"topicId":2,"subTopicId":4,"topicName":"c","subTopicName":"z"},
];


let t = [];
tst.forEach(obj => {
  // Check if the 'id' and 'subId' already exist in t 
  if (!t.find((self) => self.id === obj.topicId && self.subId === obj.subTopicId)) {
    // If not, pushes obj to t
    t.push({
      id: obj.topicId,
      subId: obj.subTopicId,
      name: obj.topicName
    });
  }
});

console.log(t);