Convert array of objects and their properties to array - javascript

I tried several of the map functions but could not find a proper way to get what I want. Here is the case:
Object {Results:Array[3]}
Results:Array[3]
[0-2]
0:Object
id=null
name: "Rick"
upper:"0.67"
1:Object
id="00379321"
name:null
upper:"0.46"
2:Object
id="00323113"
name:null
upper:null
I want my final result to look like this. I wanted all null values to be removed and all the entries tied up like this in an object.
var finalResult = ["Rick","0.67","00379321","0.46","00323113"];
How can I achieve this result?

_.chain(a)
.map(function(x) {return _.values(x)})
.flatten()
.filter(function(x) {return x != null;})
.value()

Small modification for #andrey's code (requires lodash.js)
var a = [{id:null, name: "Rick", upper:"0.67"}, {id:"00379321", name:null, upper:"0.46"}, {id: "00323113",name:null, upper:null}]
_(a)
.map(function(x) {return _.values(x)})
.flatten()
.without(null)
.value()

I suggest to use a fixed array for the keys, because the properties of an object have no order and the order is relevant.
var data = [{ id: null, name: "Rick", upper: "0.67" }, { id: "00379321", name: null, upper: "0.46" }, { id: "00323113", name: null, upper: null }],
result = [];
data.forEach(function (a) {
['id', 'name', 'upper'].forEach(function (k) {
if (a[k] !== null) {
result.push(a[k]);
}
});
});
console.log(result);

Another underscore solution, similar to the other underscore solutions, but uses reject and the isNull predicate:
var result = _.chain(data)
.map(_.values)
.flatten()
.reject(_.isNull)
.value();

Related

React - Filter JSON array if key exists [duplicate]

I have an array of objects and I'm wondering the best way to search it. Given the below example how can I search for name = "Joe" and age < 30? Is there anything jQuery can help with or do I have to brute force this search myself?
var names = new Array();
var object = { name : "Joe", age:20, email: "joe#hotmail.com"};
names.push(object);
object = { name : "Mike", age:50, email: "mike#hotmail.com"};
names.push(object);
object = { name : "Joe", age:45, email: "mike#hotmail.com"};
names.push(object);
A modern solution with Array.prototype.filter():
const found_names = names.filter(v => v.name === "Joe" && v.age < 30);
Or if you still use jQuery, you may use jQuery.grep():
var found_names = $.grep(names, function(v) {
return v.name === "Joe" && v.age < 30;
});
You can do this very easily with the [].filter method:
var filterednames = names.filter(function(obj) {
return (obj.name === "Joe") && (obj.age < 30);
});
You can learn more about it on this MDN page.
You could utilize jQuery.filter() function to return elements from a subset of the matching elements.
var names = [
{ name : "Joe", age:20, email: "joe#hotmail.com"},
{ name : "Mike", age:50, email: "mike#hotmail.com"},
{ name : "Joe", age:45, email: "mike#hotmail.com"}
];
var filteredNames = $(names).filter(function( idx ) {
return names[idx].name === "Joe" && names[idx].age < 30;
});
$(filteredNames).each(function(){
$('#output').append(this.name);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="output"/>
var nameList = [
{name:'x', age:20, email:'x#email.com'},
{name:'y', age:60, email:'y#email.com'},
{name:'Joe', age:22, email:'joe#email.com'},
{name:'Abc', age:40, email:'abc#email.com'}
];
var filteredValue = nameList.filter(function (item) {
return item.name == "Joe" && item.age < 30;
});
//To See Output Result as Array
console.log(JSON.stringify(filteredValue));
You can simply use javascript :)
For those who want to filter from an array of objects using any key:
function filterItems(items, searchVal) {
return items.filter((item) => Object.values(item).includes(searchVal));
}
let data = [
{ "name": "apple", "type": "fruit", "id": 123234 },
{ "name": "cat", "type": "animal", "id": 98989 },
{ "name": "something", "type": "other", "id": 656565 }]
console.log("Filtered by name: ", filterItems(data, "apple"));
console.log("Filtered by type: ", filterItems(data, "animal"));
console.log("Filtered by id: ", filterItems(data, 656565));
filter from an array of the JSON objects:**
var names = [{
name: "Joe",
age: 20,
email: "joe#hotmail.com"
},
{
name: "Mike",
age: 50,
email: "mike#hotmail.com"
},
{
name: "Joe",
age: 45,
email: "mike#hotmail.com"
}
];
const res = _.filter(names, (name) => {
return name.name == "Joe" && name.age < 30;
});
console.log(res);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
So quick question. What if you have two arrays of objects and you would like to 'align' these object arrays so that you can make sure each array's objects are in the order as the other array's? What if you don't know what keys and values any of the objects inside of the arrays contains... Much less what order they're even in?
So you need a 'WildCard Expression' for your [].filter, [].map, etc. How do you get a wild card expression?
var jux = (function(){
'use strict';
function wildExp(obj){
var keysCrude = Object.keys(obj),
keysA = ('a["' + keysCrude.join('"], a["') + '"]').split(', '),
keysB = ('b["' + keysCrude.join('"], b["') + '"]').split(', '),
keys = [].concat(keysA, keysB)
.sort(function(a, b){ return a.substring(1, a.length) > b.substring(1, b.length); });
var exp = keys.join('').split(']b').join('] > b').split(']a').join('] || a');
return exp;
}
return {
sort: wildExp
};
})();
var sortKeys = {
k: 'v',
key: 'val',
n: 'p',
name: 'param'
};
var objArray = [
{
k: 'z',
key: 'g',
n: 'a',
name: 'b'
},
{
k: 'y',
key: 'h',
n: 'b',
name: 't'
},
{
k: 'x',
key: 'o',
n: 'a',
name: 'c'
}
];
var exp = jux.sort(sortKeys);
console.log('#juxSort Expression:', exp);
console.log('#juxSort:', objArray.sort(function(a, b){
return eval(exp);
}));
You can also use this function over an iteration for each object to create a better collective expression for all of the keys in each of your objects, and then filter your array that way.
This is a small snippet from the API Juxtapose which I have almost complete, which does this, object equality with exemptions, object unities, and array condensation. If these are things you need or want for your project please comment and I'll make the lib accessible sooner than later.
Hope this helps! Happy coding :)
The most straightforward and readable approach will be the usage of native javascript filter method.
Native javaScript filter takes a declarative approach in filtering array elements. Since it is a method defined on Array.prototype, it iterates on a provided array and invokes a callback on it. This callback, which acts as our filtering function, takes three parameters:
element — the current item in the array being iterated over
index — the index or location of the current element in the array that is being iterated over
array — the original array that the filter method was applied on
Let’s use this filter method in an example. Note that the filter can be applied on any sort of array. In this example, we are going to filter an array of objects based on an object property.
An example of filtering an array of objects based on object properties could look something like this:
// Please do not hate me for bashing on pizza and burgers.
// and FYI, I totally made up the healthMetric param :)
let foods = [
{ type: "pizza", healthMetric: 25 },
{ type: "burger", healthMetric: 10 },
{ type: "salad", healthMetric: 60 },
{ type: "apple", healthMetric: 82 }
];
let isHealthy = food => food.healthMetric >= 50;
const result = foods.filter(isHealthy);
console.log(result.map(food => food.type));
// Result: ['salad', 'apple']
To learn more about filtering arrays in functions and yo build your own filtering, check out this article:
https://medium.com/better-programming/build-your-own-filter-e88ba0dcbfae

Pull properties from an object by their name into a different object

i'm doing a project in VueJS and i have an array of data, which consists of a number of objects.
These objects are pulled from a PHP Backend and consist of values like
id: 2123
name: "Name Value"
status: "active"
account_id: "2KGGALS2353255"
Imagine i want to split these by the keys names into a similar array but i want to have a parent object that consists of two child objects
[
0: {
core: {
id: 2123
name: "Name Value"
},
extra: {
status: "active",
account_id: "2KGGALS2353255"
}
]
The question is how can i achieve this with Javascript? I don't really want to modify the data in PHP beforehand unless this is something very unadvised to do in Javascript.
I can use VueJS and Lodash.
I was looking for lodash's pick() method.
https://lodash.com/docs/4.17.4#pick
This should work for your purpose
function separate(obj, keys) {
let target = {}, rest = {};
Object.keys(obj).forEach(function(key) {
if (keys.includes(key)) {
target[key] = obj[key];
} else {
rest[key] = obj[key];
}
});
return { target: target, rest: rest };
}
let stuff = {
id: 2123,
name: "Name Value",
status: "active",
account_id: "2KGGALS2353255"
};
let separated = separate(stuff, ['id', 'name']);
console.log({
core: separated.target,
extra: separated.rest
});
Using ES6's object destructuring, and the object rest spread proposal, which requires a babel transform, you can Array#map the array into a new array of objects in the required format:
const arr = [{"id":1,"name":"Name1","status":"active","account_id":"2KGGALS2353255"},{"id":2,"name":"Name2","status":"active","account_id":"4ABCLS2353255"},{"id":3,"name":"Name3","status":"active","account_id":"6LMNALS2353255"}];
const result = arr.map(({ id, name, ...extra }) => ({
core: {
id,
name
},
extra
}));
console.log(result);
You can do the same thing using lodash's _.pick() to the get the core, and _.omit() to get the extra:
var arr = [{"id":1,"name":"Name1","status":"active","account_id":"2KGGALS2353255"},{"id":2,"name":"Name2","status":"active","account_id":"4ABCLS2353255"},{"id":3,"name":"Name3","status":"active","account_id":"6LMNALS2353255"}];
var result = arr.map(function(obj) {
return {
core: _.pick(obj, ['id', 'name']),
extra: _.omit(obj, ['id', 'name'])
};
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

Removing specific key-value pairs from a document/object

I have a document that looks like something like this:
{
name: "Johnny Boy",
age: 24,
hobbies: ["fencing", "chess", "raves"],
_createdAt: 2015-05-15T18:12:26.731Z,
_createdBy: "JohnnyBoy",
_id: mQW4G5yEfZtsB6pcN
}
My goal is to return everything that doesn't start with an underscore, and format it a bit differently so I will end up with this:
[
{
fieldName: "name",
value: "Johnny Boy"
},
{
fieldName: "age",
value: 24
},
{
fieldName: "hobbies",
value: ["fencing", "chess", "raves"]
}
]
My initial solution was to run it through the _.map function of the Underscore library (which has nothing to do with my wanting to remove underscores specifically...) and then using lastIndexOf to figure out which keys begin with an underscore:
var listWithoutUnderscores = _.map(myList, function(val, key) {
if (key.lastIndexOf("_", 0) === -1)
return {fieldName: key, value: val}
return null
})
However, this will literally return null instead of the fields that began with _ in the returned array:
[
...
{
fieldname: "hobbies",
value: ["fencing", "chess", "raves"]
},
null,
null,
null
]
I want to remove them completely, ideally within the map function itself, or else by chaining it through some kind of filter but I don't know which one is fastest in this case.
You can use reduce for this:
var listWithoutUnderscores = _.reduce(myList, function(list, val, key) {
if (key.lastIndexOf("_", 0) === -1){
list.push( {fieldName: key, value: val});
}
return list;
}, []);
Underscore also comes with an array method compact which will remove all falsey and null values from an array:
_.compact([0, 1, false, 2, '', null, 3]);
=> [1, 2, 3]
You could just call _.compact(array) on the array after your map.
You can use pick and pass a predicate to get the valid keys and then map across those fields:
var validKey = function(value, key){
return _.first(key) != '_';
}
var createField = function(value, key){
return {
fieldname: key,
value: value
}
}
var result = _.chain(data)
.pick(validKey)
.map(createField)
.value();
var data = {
name: "Johnny Boy",
age: 24,
hobbies: ["fencing", "chess", "raves"],
_createdAt: '2015-05-15T18:12:26.731Z',
_createdBy: "JohnnyBoy",
_id: 'mQW4G5yEfZtsB6pcN'
}
var validKey = function(value, key){
return _.first(key) != '_';
}
var createField = function(value, key){
return {
fieldname: key,
value: value
}
}
var result = _.chain(data)
.pick(validKey)
.map(createField)
.value();
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>

How can I get a unique array based on object property using underscore

I have an array of objects and I want to get a new array from it that is unique based only on a single property, is there a simple way to achieve this?
Eg.
[ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
Would result in 2 objects with name = bill removed once.
Use the uniq function
var destArray = _.uniq(sourceArray, function(x){
return x.name;
});
or single-line version
var destArray = _.uniq(sourceArray, x => x.name);
From the docs:
Produces a duplicate-free version of the array, using === to test object equality. If you know in advance that the array is sorted, passing true for isSorted will run a much faster algorithm. If you want to compute unique items based on a transformation, pass an iterator function.
In the above example, the function uses the objects name in order to determine uniqueness.
If you prefer to do things yourself without Lodash, and without getting verbose, try this uniq filter with optional uniq by property:
const uniqFilterAccordingToProp = function (prop) {
if (prop)
return (ele, i, arr) => arr.map(ele => ele[prop]).indexOf(ele[prop]) === i
else
return (ele, i, arr) => arr.indexOf(ele) === i
}
Then, use it like this:
const obj = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ]
obj.filter(uniqFilterAccordingToProp('abc'))
Or for plain arrays, just omit the parameter, while remembering to invoke:
[1,1,2].filter(uniqFilterAccordingToProp())
If you want to check all the properties then
lodash 4 comes with _.uniqWith(sourceArray, _.isEqual)
A better and quick approach
var table = [
{
a:1,
b:2
},
{
a:2,
b:3
},
{
a:1,
b:4
}
];
let result = [...new Set(table.map(item => item.a))];
document.write(JSON.stringify(result));
Found here
You can use the _.uniqBy function
var array = [ { id: 1, name: 'bob' }, { id: 2, name: 'bill' }, { id: 1, name: 'bill' },{ id: 2, name: 'bill' } ];
var filteredArray = _.uniqBy(array,function(x){ return x.id && x.name;});
console.log(filteredArray)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.js"></script>
In the above example, filtering is based on the uniqueness of combination of properties id & name.
if you have multiple properties for an object.
then to find unique array of objects based on specific properties, you could follow this method of combining properties inside _.uniqBy() method.
I was looking for a solution which didn't require a library, and put this together, so I thought I'd add it here. It may not be ideal, or working in all situations, but it's doing what I require, so could potentially help someone else:
const uniqueBy = (items, reducer, dupeCheck = [], currentResults = []) => {
if (!items || items.length === 0) return currentResults;
const thisValue = reducer(items[0]);
const resultsToPass = dupeCheck.indexOf(thisValue) === -1 ?
[...currentResults, items[0]] : currentResults;
return uniqueBy(
items.slice(1),
reducer,
[...dupeCheck, thisValue],
resultsToPass,
);
}
const testData = [
{text: 'hello', image: 'yes'},
{text: 'he'},
{text: 'hello'},
{text: 'hell'},
{text: 'hello'},
{text: 'hellop'},
];
const results = uniqueBy(
testData,
item => {
return item.text
},
)
console.dir(results)
In case you need pure JavaScript solution:
var uniqueProperties = {};
var notUniqueArray = [ { id: 1, name: 'bob' }, { id: 1, name: 'bill' }, { id: 1, name: 'bill' } ];
for(var object in notUniqueArray){
uniqueProperties[notUniqueArray[object]['name']] = notUniqueArray[object]['id'];
}
var uniqiueArray = [];
for(var uniqueName in uniqueProperties){
uniqiueArray.push(
{id:uniqueProperties[uniqueName],name:uniqueName});
}
//uniqiueArray
unique array by id property with ES6:
arr.filter((a, i) => arr.findIndex(b => b.id === a.id) === i); // unique by id
replace b.id === a.id with the relevant comparison for your case

underscore.js filter an array of objects, based on another

I am trying to filter an array of objects, based on another. The common property id id.
I am not sure filter + each is the best way to do it or map reduce. Anyway, below code doesn't work as out is empty list.
var aaa = [
{name: "AAA", id: 845},
{name: "BBB", id: 839},
{name: "CCC", id: 854}
];
var bbb = [
{id: 839},
{id: 854}
];
var out = _.filter(aaa, function(val){
return _.each(this, function(val2){
return val['id'] === val2['id']
});
}, bbb);
Just create a "set" of the valid ids and use that "set" to do the filtering:
var aaa = [
{name: "AAA", id: 845},
{name: "BBB", id: 839},
{name: "CCC", id: 854}
];
var bbb = [
{id: 839},
{id: 854}
];
var ids = {};
_.each(bbb, function (bb) { ids[bb.id] = true; });
var out = _.filter(aaa, function (val) {
return ids[val.id];
}, bbb);
Filling ids is fast, it's in n * amortized O(1), i.e O(n). Same holds for the filtering.
If you use each(…) in the inner loop, you will have O(n²). For bigger data sets this would become very slow. Also the additional nesting make the code more difficult to read/understand at first glance.
See that code snipped in action: http://jsfiddle.net/SMtX5/
you can use _.find to filter:
_.filter(aaa, function(a){
return _.find(bbb, function(b){
return b.id === a.id;
});
});
You can use _.some(list, [iterator], [context]).
It returns true if any of the values in the list pass the iterator truth test.
var out = _.filter(aaa, function(val){
return _.some(this,function(val2){
return val2['id'] === val['id'];
});
}, bbb);
Here is jsfiddle. http://jsfiddle.net/h98ej/
bbb = bbb.map(_ => _.id) && aaa.filter(_ => bbb.indexOf( _.id ) > -1)
You just need pure JS array functions to do that assuming your use case.

Categories

Resources