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: /
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/ksumarine/ss3v7dgj/
Share Improve this question asked Feb 16, 2016 at 19:11 ksumarineksumarine 7822 gold badges13 silver badges33 bronze badges 2- Premature optimization is the root of all evil -- DonaldKnuth – Michael Hobbs Commented Feb 16, 2016 at 19:17
- Agreed, unfortunately that's the data I have to work with :/ – ksumarine Commented Feb 16, 2016 at 19:20
6 Answers
Reset to default 3I 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(', '); })))
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"]
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/ss3v7dgj/1/
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>');
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...
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:
- we take the list and for each item, we reduce it ...
- from each item, we extract the
seenby
field - we
split
the field - we
map
each item totrim
it
- from each item, we extract the
- ... we take the array of returned
seenby
and concatenate them to our accumulator arrayarr
(which is initialized as empty array[]
) - then we filter out the duplicates from the array (by checking whether the index of an item is the same as the current index)
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744825609a4595775.html
评论列表(0条)