extract fields from object - javascript

If I have this:
var myObj = [
{ name: 'A', number: 'b1',level: 0 },
{ name: 'B', number: 'b2',level: 0 },
];
How can I extract all the names like:
"names": {
'A',
'B'
}

You could use this function to get an array of values, not object properties (which are not suited for that):
function getColumn(arr, column) {
return arr.map(function (rec) { return rec[column] });
}
// Sample data
var myObj = [
{ name: 'A', number: 'b1',level: 0 },
{ name: 'B', number: 'b2',level: 0 },
];
// Get names
var names = getColumn(myObj, 'name');
// Output
console.log(names);

Related

Remove duplicated combination in array based on index

I have the following data array:
const data = [
{
value: [
'a',
'b',
'a',
'a'
]
},
{
value: [
'c',
'c',
'd',
'c'
]
}
];
So there's is 4 combination here based on index:
combination 1 : a - c (index 0 in each value arrays)
combination 2 : b - c (index 1 in each value arrays)
combination 3 : a - d (index 2 in each value arrays)
combination 4 : a - c (index 3 in each value arrays)
As you can see the first and the last combinations are the same, so i want to remove the second occurrence from each array, the result should be:
[
{
value: [
'a',
'b',
'a'
]
},
{
value: [
'c',
'c',
'd'
]
}
]
You can zip the values arrays from both objects to form an array which looks like:
["a-c", "b-c", ...]
As these are now strings, you can turn this array into a Set using new Set(), which will remove all duplicate occurrences. You can then turn this set back into an array which you can then use .reduce() on to build you array of objects from. For each value you can obtain the list of values by using .split() on the '-', and from that, populate your reduced array.
See example below:
const data = [{ value: [ 'a', 'b', 'a', 'a' ] }, { value: [ 'c', 'c', 'd', 'c' ] } ];
const unq = [...new Set(
data[0].value.map((_,c)=> data.map(({value})=>value[c]).join('-'))
)];
const res = unq.reduce((acc, str) => {
const values = str.split('-');
values.forEach((value, i) => acc[i].value.push(value));
return acc;
}, Array.from({length: data.length}, _ => ({value: []})))
console.log(res);
Limitations of the above method assume that you won't have a - character as your string value. If this is an issue, you can consider using a different delimiter, or find unique values within your array using .filter() instead of a Set.
You could save a lookup object for unique pairs of value based with index
Given your input is, below solution could help you
const data = [
{
value: ["a", "b", "a", "a"],
},
{
value: ["c", "c", "d", "c"],
},
]
const lookup = {}
data[0].value.forEach((_, index) => {
lookup[`${data[0].value[index]}-${data[1].value[index]}`] = true
})
const res = Object.keys(lookup).reduce(
(acc, key) => {
const [val1, val2] = key.split("-")
acc[0].value.push(val1)
acc[1].value.push(val2)
return acc
},
[{ value: [] }, { value: [] }]
)
console.log(res)
Below is a two step solution with a generator function and a single pass.
const data = [ { value: [ 'a', 'b', 'a', 'a' ] }, { value: [ 'c', 'c', 'd', 'c', ] } ];
const zipDataValues = function* (data) {
const iterators = data.map(item => item.value[Symbol.iterator]())
let iterations = iterators.map(iter => iter.next())
while (iterations.some(iteration => !iteration.done)) {
yield iterations.map(iteration => iteration.value)
iterations = iterators.map(iter => iter.next())
}
}
const filterOutDuplicateCombos = function (values) {
const combosSet = new Set(),
resultData = [{ value: [] }, { value: [] }]
for (const [valueA, valueB] of values) {
const setKey = [valueA, valueB].join('')
if (combosSet.has(setKey)) {
continue
}
combosSet.add(setKey)
resultData[0].value.push(valueA)
resultData[1].value.push(valueB)
}
return resultData
}
console.log(
filterOutDuplicateCombos(zipDataValues(data))
) // [ { value: [ 'a', 'b', 'a' ] }, { value: [ 'c', 'c', 'd' ] } ]
Here is a reference on generators and iterators
Filter combinations + sorting by the first occurrence:
const data = [{
value: ['a', 'b', 'a', 'a']
},{
value: ['c', 'c', 'd', 'c']
}];
var res = {}, i, t;
for (i = 0; i < data[0].value.length; ++i) {
res[data[0].value[i]] = res[data[0].value[i]] || {};
res[data[0].value[i]][data[1].value[i]] = true;
}
data[0].value = [];
data[1].value = [];
for (i in res) {
for (t in res[i]) {
data[0].value[data[0].value.length] = i;
data[1].value[data[1].value.length] = t;
}
}
console.log(data);

Looking to group array by values in the sub array

Trying to parse one data set that has a bunch of the same "secondaryIDs" in way that i can group and iterate through them together.
In english what im trying to do is
"select a unique group of all items where the value of field is unique "
'use strict';
const data = [{
Group: 'A',
Name: 'SD'
}, {
Group: 'B',
Name: 'FI'
}, {
Group: 'A',
Name: 'MM'
}, {
Group: 'B',
Name: 'CO'
}];
let unique = [...new Set(data.map(item => item.Group))];
console.log(unique);
Which gives ["A"],["B"]
but what im looking for is
{
A: [ "SD","MM" ],
B: [ "FI","CO" ],
}
For this, I would use array.reduce instead of array.map because what you're actually hoping to return is a new value, not a modified array, the reduce method is perfect when you want to literally reduce the array into a single output value, in your case an object of unique groups. Maybe try something like this:
let unique = data.reduce((acc, { Group, Name }) => {
if (!(acc.hasOwnProperty(Group))) {
acc[Group] = [Name];
} else {
acc[Group].push(Name);
};
return acc;
}, {});
I've also added a pen for this at: https://codepen.io/anon/pen/BGpgdz?editors=1011 so you can see this working.
Hope this helps!
You can also reduce your array to the grouped object (keyed by Group values):
const data = [{
Group: 'A',
Name: 'SD'
}, {
Group: 'B',
Name: 'FI'
}, {
Group: 'A',
Name: 'MM'
}, {
Group: 'B',
Name: 'CO'
}];
const grouped = data.reduce((a, {Group, Name}) => {
if (!(Group in a)) a[Group] = [Name];
else a[Group].push(Name);
return a;
}, {});
console.log(grouped);
can do something like..
const map = {};
data.forEach( d => {
if( map[d.Group] ) {
map[d.Group].push(d.Name);
} else {
map[d.Group] = [d.Name];
}
})
console.log(map)
I think the easiest way to achieve this would be to use Array.prototype.reduce method to create an object that maps unique Group names to arrays that contain Names. You can supply an empty object literal as your initial reduce accumulator:
const data = [{
Group: 'A',
Name: 'SD'
}, {
Group: 'B',
Name: 'FI'
}, {
Group: 'A',
Name: 'MM'
}, {
Group: 'B',
Name: 'CO'
}];
var namesByGroup = data.reduce((map, el) => {
map[el.Group] ? map[el.Group].push(el.Name) : map[el.Group] = [el.Name];
return map;
}, {});
console.log(namesByGroup);
If you're interested in a functional approach, here is a solution using Ramda:
const group =
R.pipe(
R.groupBy(R.prop('Group')),
R.map(R.map(R.prop('Name'))));
console.log(
group([
{Group: 'A', Name: 'SD'},
{Group: 'B', Name: 'FI'},
{Group: 'A', Name: 'MM'},
{Group: 'B', Name: 'CO'}])
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
can also be done using forEach
const data = [{
Group: 'A',
Name: 'SD'
}, {
Group: 'B',
Name: 'FI'
}, {
Group: 'A',
Name: 'MM'
}, {
Group: 'B',
Name: 'CO'
}];
const somefunction = (data) => {
let arr = {}
data.forEach( ({Group, Name}) => {
Group in arr ? arr[Group].push(Name) : arr[Group] = [Name]
})
return arr;
}
console.log(somefunction(data))

How to manipulate an array by grouping items into arrays

Let's say I have this array:
let obj = [
{ prop: 'a', val: 2 },
{ prop: 'a', val: 1 },
{ prop: 'b', val: 3 },
{ prop: 'b', val: 1 }
]
Let's say i want to get an array for each existing prop val:
let myArr = [
[ { prop: 'a', val: 2 }, { prop: 'a', val: 1 } ]
[ { prop: 'b', val: 3 }, { prop: 'b', val: 1 } ]
]
how would you do that by using high order functions?
function sumProps(arr) {
const sum = arr.reduce((ac,cv) => {
if (ac[cv] === undefined) ac[cv.prop] = ac[cv.prop] = cv.val;
else ac[cv.prop] += cv.val;
}, {});
const res = [];
for (const p in sum) {
res.push({ prop:p, sum:sum[p] });
}
return res;
}
You could reduce the objects by looking for an object with same prop and update the value.
var array = [{ prop: 'a', val: 2 }, { prop: 'a', val: 1 }, { prop: 'b', val: 3 }, { prop: 'b', val: 1 }],
result = array.reduce((r, o) => {
var temp = r.find(({ prop }) => prop === o.prop);
if (temp) {
temp.val += o.val;
} else {
r.push(Object.assign({}, o));
}
return r
}, []);
console.log(result);

JavaScript | AngularJS: Filter Collection by Nested Value

Filter Collection by Nested Item in Array
Say there's a collection:
[ { key: '', param: '', array: ['a', 'b', 'c'] },... ]
Using [Angular] $filter('filter'), how can I return a collection of objects whose .array contains the specified value 'c'?
For instance, one could imagine writing the following.
var token = 'c';
var query = { array: token };
var anyWithC = filter(collection, query, true);
This doesn't seem to work so I've tried...
var query = { array: [token] };
I don't think this is working either.
Could someone set me straight on this one? Is this possible to filter this way? Must I use a function instead of a query object?
Use Underscore library's _.filter(list, predicate);
Working demo
var sample = [{
name: 'test',
lastName: 'test',
address: ['a', 'b', 'c']
}, {
name: 'test1',
lastName: 'test1',
address: ['d', 'e', 'f']
}, {
name: 'test2',
lastName: 'test2',
address: ['g', 'h', 'i']
}];
//key is the objecy key from which the value will be extracted to compare with the token.
function filterByKey(list, key, token) {
var filterArray = _.filter(list, function(value) {
//If Undefined value then should return false
if (_.isUndefined(value[key])) {
return false;
} else if (_.isArray(value[key])) {
//Checks the extracted value is an Array
return _.contains(value[key], token);
}else {
return value[key] === token;
}
});
return filterArray;
}
console.log('Output ------------- ', filterByKey(sample, 'address', 'h'));
You can use lodash
https://lodash.com/docs
Have created a JSFiddle using angular and lodash:
https://jsfiddle.net/41rvv8o8/
This is based on the data you provided, and this demo is not case sensitive (upper and lower cases).
HTML
<div ng-app="app">
<example-directive>
</example-directive>
</div>
Javascript
var app = angular.module('app',[]);
app.directive('exampleDirective', function() {
return {
template:'<h1>Collections with array containing c</h1><ul><li ng-repeat="collection in matchcollections">key: {{collection.key}}, param: {{collection.param}}, <div ng-repeat="item in collection.array">{{item}}</div></li></ul>',
controller: function($scope){
$scope.collections = [ { key: 'A', param: 'A1', array: ['a', 'b', 'c'] },{ key: 'B', param: 'B1', array: ['x', 'h', 'c'] },{ key: 'C', param: 'C', array: ['t', 'a', 'k'] }];
$scope.matchcollections = _.filter($scope.collections, function(c){
return _.includes(c.array,'c')
});
console.log("Collection with match: ", $scope.matchcollections);
}
}
});
Hope this helps!

group array by groups and sort by position

I have an array. I need to group this array by groups and sort by position. I tied to create a new array with group names as keys and values as sorted array grouped by group, but didn't work well. How can I do this?
a = [
{id:1,name:'qw'group:'C',name:'hite',position:'1'},
{id:2,name:'qwe'group:'B',name:'ite',position:'2'},
{id:3,name:'qwer'group:'A',name:'ite',position:'3'},
{id:4,name:'qer'group:'D',name:'te',position:'4'},
{id:5,name:'wer'group:'C',name:'whit',position:'5'},
{id:6,name:'er'group:'B',name:'whi',position:'6'},
]
function groupDo(array){
var groups = [];
for (var i in array){
groups[array[i].group] = array[i].group;
}
for (var i in array){
if (groups[array[i].group] == array[i].group){
groups[array[i].group] = array[i];
}
}
}
Here's a simple straight forward answer:
var sortByPosition = function(obj1, obj2) {
return obj1.position - obj2.position;
};
var arr = [
{ id: 1, name: 'qw', group: 'C', name: 'hite', position: '1' },
{ id: 2, name: 'qwe', group: 'B', name: 'ite', position: '2' },
{ id: 3, name: 'qwer', group: 'A', name: 'ite', position: '3' },
{ id: 4, name: 'qer', group: 'D', name: 'te', position: '4' },
{ id: 5, name: 'wer', group: 'C', name: 'whit', position: '5' },
{ id: 6, name: 'er', group: 'B', name: 'whi', position: '6' },
];
var grouped = {};
for (var i = 0; i < arr.length; i += 1) {
if(!grouped[arr[i].group]) {
grouped[arr[i].group] = [];
}
grouped[arr[i].group].push(arr[i]);
}
for (var group in grouped) {
grouped[group] = grouped[group].sort(sortByPosition);
}
console.log(grouped);
When you want to do stuff like this though, it's usually recommended to use a utility library like lodash or underscore.js, so that you don't have to "reinvent the wheel". Here's how it would look like using one of these libraries:
var arr = [
{ id: 1, name: 'qw', group: 'C', name: 'hite', position: '1' },
{ id: 2, name: 'qwe', group: 'B', name: 'ite', position: '2' },
{ id: 3, name: 'qwer', group: 'A', name: 'ite', position: '3' },
{ id: 4, name: 'qer', group: 'D', name: 'te', position: '4' },
{ id: 5, name: 'wer', group: 'C', name: 'whit', position: '5' },
{ id: 6, name: 'er', group: 'B', name: 'whi', position: '6' },
];
var grouped = _.groupBy(arr, 'group');
for (var group in grouped) {
_.sortBy(grouped[group], 'position');
}
console.log(grouped);
Here ya go!
a = [
{id:1,name:'qw',group:'C',name:'hite',position:'1'},
{id:2,name:'qwe',group:'B',name:'ite',position:'2'},
{id:3,name:'qwer',group:'A',name:'ite',position:'3'},
{id:4,name:'qer',group:'D',name:'te',position:'4'},
{id:5,name:'wer',group:'C',name:'whit',position:'5'},
{id:6,name:'er',group:'B',name:'whi',position:'6'},
]
function groupAndSort(array, groupField, sortField) {
var groups = {}; // This object will end being keyed by groups, and elements will be arrays of the rows within the given array, which have been sorted by the sortField
// Put all the rows into groups
for (var i = 0; i < array.length; i++) {
var row = array[i];
var groupValue = row[groupField];
groups[groupValue] = groups[groupValue] || [];
groups[groupValue].push(row);
}
// Sort each group
for (var groupValue in groups) {
groups[groupValue] = groups[groupValue].sort(function(a, b) {
return a[sortField] - b[sortField];
});
}
// Return the results
return groups;
}
var groupedAndSorted = groupAndSort(a, "group", "position");
If you want to group objects, first think about what the resulting data would look like. Maybe something like this?
var grouped = {
A : [
{id:3,name:'qwer', group:'A',name:'ite',position:'3'}
],
B : [],
C : [],
D : []
};
And so on. To transform a list into an object, consider using .reduce().
.reduce() takes a function as its first argument, and a resulting object as the second. The function iterates through each element of the array and reduces it into the given object.
var data = [
{id:1,name:'qw', group:'C',name:'hite',position:'1'},
{id:2,name:'qwe', group:'B',name:'ite',position:'2'},
{id:3,name:'qwer', group:'A',name:'ite',position:'3'},
{id:4,name:'qer', group:'D',name:'te',position:'4'},
{id:5,name:'wer', group:'C',name:'whit',position:'5'},
{id:6,name:'er', group:'B',name:'whi',position:'6'},
]
// acc is the accumulated object, x is each element of the array
data.reduce(function(acc, x) {
// first check if the given group is in the object
acc[x.group] = acc[x.group] ? acc[x.group].concat(x) : [x];
return acc;
}, {}); // this is the resulting object
Now all you need to do is use the built in sort to order the resulting arrays. You could do this by iterating through the keys of the resulting object and applying .sort() to each array. .sort() takes a function as an argument which accesses the data and provides a comparison function.
// a and b are elements of the array
array.sort(function(a, b) {
if (a.position > b.position) {
return -1;
} else if (b.position > a.position) {
return 1;
} else {
return 0;
}
});
And you would implement it like so
var result = Object.keys(data).map(function(d){
return d.sort(f); // f is the function above
});

Categories