Reputation: 782
I would like to take an array of objects:
var objArr = [
{id:1, name:'test', seenby:'user1, user2, user3'},
{id:2, name:'test1', seenby:'user3, user4'},
{id:3, name:'test2', seenby:'user1, user3'},
{id:4, name:'test3', seenby:'user2'}
];
And return a distinct array of all 'seenby' users:
var seenByArr = ['user1', 'user2', 'user3', 'user4']
I can't figure out how to efficiently (fewest lines possible) turn this into an array of distinct values. Please check out my fiddle for an example: https://jsfiddle.net/ksumarine/ss3v7dgj/
Upvotes: 3
Views: 1190
Reputation: 726
I would use the Array.prototype.map
function, and de-duplicate the users in a associative array. So here the interesting part, but you can also try it out here:
var list = [
{id:1, name:'test', seenby:'user1, user2, user3'},
{id:2, name:'test1', seenby:'user3, user4'},
{id:3, name:'test2', seenby:'user1, user3'},
{id:4, name:'test3', seenby:'user2'}
];
var arr = [];
list.map(function(value){
value.seenby.split(",").map(function(val){
arr[val.trim()] = 1;
});
});
var seenby = Object.keys(arr);
How does it work? The map
function will iterate over all the list
items, the next map will iterate over all the seenby
items. We then collect the users in the arr
, de-duplicating by using it as an associative array.
At the end we extract all the associative array keys by using the Object.keys
function.
Minor caveat is that this solution will only work if the map function exists, if it doesn't you would need to implement it yourself. But usually you are using a new enough JavaScript version that does support it. This solution also has the nice side effect that you don't really need any external dependency (except of course for displaying it)
UPDATE: I think it's actually better to do it the following way:
var arr = list
.reduce(function(acc, value){
return acc.concat(value.seenby.split(",").map(function(val){
return val.trim()
}))},[])
.filter(function(item, index, array) {
return array.indexOf(item) === index
}
)
Explanation:
seenby
fieldsplit
the fieldmap
each item to trim
itseenby
and concatenate them to our accumulator array arr
(which is initialized as empty array []
)Upvotes: 1
Reputation: 92854
The laconic solution with String.split
and Array.foreach
functions:
var arr = [];
objArr.forEach(function (obj) {
var str = obj.seenby.split(',');
str.forEach(function (v) {
var user = v.trim();
if (arr.indexOf(user) === -1) arr.push(user);
});
});
console.log(arr);
// the output:
["user1", "user2", "user3", "user4"]
Upvotes: 2
Reputation: 214959
given = function (x) {
return {
do: function (f) { x = f(x); return this },
return: function () { return x }
}
};
r = given(objArr)
.do(x => x.map(y => y.seenby))
.do(x => [].concat.apply([], x))
.do(x => x.join(', '))
.do(x => x.split(', '))
.do(x => x.filter((e, i) => x.indexOf(e) === i))
.do(x => x.sort())
.return();
I might find use for this someday...
Upvotes: 1
Reputation: 386624
A solution in plain Javascript with an IIFE and a temporary object for the items.
var objArr = [{ id: 1, name: 'test', seenby: 'user1, user2, user3' }, { id: 2, name: 'test1', seenby: 'user3, user4' }, { id: 3, name: 'test2', seenby: 'user1, user3' }, { id: 4, name: 'test3', seenby: 'user2' }],
result = function (array) {
var obj = {}, r = [];
array.forEach(function (a) {
a.seenby.split(', ').forEach(function (b) {
obj[b] = obj[b] || r.push(b);
});
});
return r;
}(objArr);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
Upvotes: 1
Reputation: 28455
You can try following
$.each(list, function(index, value) {
$.each(value.seenby.split(","), function(i, val) {
if (val !== undefined && val.trim() !== "" && arr.indexOf(val.trim()) == -1) {
arr.push(val.trim());
}
});
});
For reference - https://jsfiddle.net/ss3v7dgj/1/
Upvotes: 1
Reputation: 14327
I realize this question doesn't mention Underscore, but it's worth mentioning that Underscore.js is a very popular library for manipulating objects and arrays, and well-suited for this kind of thing.
Here's a big unreadable single line for achieving this with Underscore:
_.unique(_.flatten(_.map(_.pluck(objArr, 'seenby'), function(seenby) { return seenby.split(', '); })))
Upvotes: 3