loop through a javascript array add the value to another array - javascript

how to loop through this array , I want to loop and and add name value to an empty array , when I console .log it gives the results below, could you please help , the result of my code is empty array
this.props.names
it shows
(3) [{…}, {…}, {…}] 0: {name: "abc", id: 1} 1: {name: "def", id: 2} 2:
{name: "gh", id: 3} length: 3
proto: Array(0)
let titles = []
let cats = []
cats = this.props.names
let len = this.props.names.length;
for( i = 0 ;i< cats.length ; i++){
titles.push(cats[i].id)
}
return titles;

from what i see... do
let titles = []
let cats = [{name: "abc", id: 1},{name: "def", id: 2},{name: "gh", id: 3}]
for( var p = 0 ;p< cats.length ; p++){
titles.push(cats[p].id)
}
console.log(titles)

If you simply want to extract the ids, and props and/or names may be empty or null, you can do it using map:
const titles = (props && props.names || []).map(val => val.id);
Here props && props.names || [] will be equal to [] if props or props.names evaluates to falsy. That way, you can still apply map to it, which will return an empty array in this case.
function demo(props) {
const titles = (props && props.names || []).map(val => val.id);
console.log(titles);
}
demo({ names: [{name: 'one', id: 1}, {name: 'two', id: 2}, {name: 'three', id: 3}] });
demo({ names: [] });
demo({});
demo(null);
See the MDN doc about the map operator.

Related

Filtering an array of objects from an array

I have an array of objects lookups and an array filters. Now I want to filter the array from an array of objects using the object attribute name.
I used filter and some but I could not get the expected result.
EXPECTED RESULT:
[{id: 3, name: "Linkedin"}]
let lookups = [
{id: 1, name: "Twitter"},
{id: 2, name: "Facebook"},
{id: 3, name: "Linkedin"}
]
let filters = ["Facebook", "Twitter"]
const filtered = lookups.filter(lookup => filters.some(filter => filter.toLowerCase() != lookup.name.toLowerCase()));
console.log(filtered)
Your code gives those elements in result for which some of the values in filters is not equal to element's name. So for each element some of the name is not equal.
In other words you are using != with || which will always return true.
let a = "anything";
console.log(a !== "thing1" || a !== "thing2")
You need to use every() instead of some().
let lookups = [
{id: 1, name: "Twitter"},
{id: 2, name: "Facebook"},
{id: 3, name: "Linkedin"}
]
let filters = ["Facebook", "Twitter"]
const filtered = lookups.filter(lookup => filters.every(filter => filter.toLowerCase() !== lookup.name.toLowerCase()));
console.log(filtered)

Compare object array with object and reduce quantity

I have an object containing an id as the key, and quantity as the value, e.g.;
let order = {1002: 2, 1010: 1}
I want to compare the order object with an array of products, e.g.:
let stock = [{name: "test", id: "1002", quantity: 100}, {name: "moreTest", id: "1010", quantity: 100}]
I want to reduce the quantity for each object in my stocks array, based on the according value in the stocks object, e.g.:
let newStock = [{name: "test", id: "1002", quantity: 98}, {name: "moreTest", id: "1010", quantity: 99}]
Here's a one-liner approach:
let newStock = stock.map(item => ({...item, quantity: item.quantity - (order[parseInt(item.id,10)] || 0)}))
BTW:
I think stock's id should be a number (or order needs to have a string key - I used parseInt but I don't think it's the best practice).
stock should be a map as well to prevent multiple stocks with the same id.
Here is a possible solution, very clear:
let order = {1002: 2, 1010: 1}
let stock = [{name: "test", id: "1002", quantity: 100}, {name: "moreTest", id: "1010", quantity: 100}]
stock.forEach(element => {
Object.keys(order).forEach(function(key) {
const quantityBought = order[key];
// == and not === because element.id is a string and key is a number
if (element.id == key) {
element.quantity -= quantityBought;
}
});
});
console.log(stock);
You can use Array.prototype.reduce here something Like this
let stock = [{name: "test", id: "1002", quantity: 100}, {name: "moreTest", id: "1010", quantity: 100}]
let order = {1002: 2, 1010: 1}
let result=stock.reduce((acc,value)=>{
value.quantity=value.quantity-order[value.id];
acc.push(value);
return acc;
},[])
console.log(result)
For reference look at array reduce function in mozilla docs

Why Array helper Filter is returning a null value

I am new to JavaScript and while learning it trying to filter an employee based on education but my filter is returning a null value. Can anyone help me understand why is this so?
var employeeEdu = [{education: 'Masters'}];
var employees = [{id: 1, age: 35, name: 'James', dept: 'IT', education: 'Masters'},
{id: 2, age: 25, name: 'David', dept: 'Accounts', education: 'High School'},
{id: 3, age: 45,name: 'Tim', dept: 'HR', education: 'Graduate'},
{id: 4, age: 50,name: 'Vinod', dept: 'IT', education: 'PHD'}];
function chooseQualified(arrEmployee, empEducation) {
return arrEmployee.filter(function(emp) {
return emp.education === empEducation.education;
// return emp.education === 'Masters';
});
}
console.log(chooseQualified(employees, employeeEdu));
It's because employeeEdu is an array, and employeeEdu.education is undefined. What you need to do is to checkout employeeEdu[0].education:
var employeeEdu = [{education: 'Masters'}];
var employees = [{"id":1,"age":35,"name":"James","dept":"IT","education":"Masters"},{"id":2,"age":25,"name":"David","dept":"Accounts","education":"High School"},{"id":3,"age":45,"name":"Tim","dept":"HR","education":"Graduate"},{"id":4,"age":50,"name":"Vinod","dept":"IT","education":"PHD"}];
function chooseQualified(arrEmployee, empEducation) {
return arrEmployee.filter(function(emp) {
return emp.education === empEducation[0].education;
// return emp.education === 'Masters';
});
}
console.log(chooseQualified(employees, employeeEdu));
Another solution is to remove the wrapping array:
employeeEdu = {education: 'Masters'};
Like #Ori Drori says, employeeEdu is an array, so empEducation.education is undefined, but empEducation[0].education is 'Masters'. I suggest that employeeEdu be a object instead of array, like below code. var employeeEdu = {education: 'Masters'};
var employeeEdu = {education: 'Masters'};
var employees = [{id: 1, age: 35, name: 'James', dept: 'IT', education: 'Masters'},
{id: 2, age: 25, name: 'David', dept: 'Accounts', education: 'High School'},
{id: 3, age: 45,name: 'Tim', dept: 'HR', education: 'Graduate'},
{id: 4, age: 50,name: 'Vinod', dept: 'IT', education: 'PHD'}];
function chooseQualified(arrEmployee, empEducation) {
return arrEmployee.filter(function(emp) {
return emp.education === empEducation.education;
// return emp.education === 'Masters';
});
}
console.log(chooseQualified(employees, employeeEdu));
/* #Params:
* array0 [Array of Objects]: Array to search through.
* array1 [Array of Objects]: Array with the key/value to search for.
* key [String]: Key of the object in array1.
* index [Number](optional): Index of array1. default: 0.
*/
// Returns a new array of objects witch matched by key/value from the two given arrays.
function findByKV(array0, array1, key, index = 0) {
// Get the value of the key to be searched for
var value = array1[index][key];
// Filter the array to be searched obj is each Object in array1
filter()
array0.filter(function(obj) {
// Get each obj key of array0 and ...
Object.keys() .some()
return Object.keys(obj).some(function(key) {
// ...return true if at least one String value matches the value of the key in array1
.toString() .indexOf()
return obj[key].toString().indexOf(value) != -1;
var target0 = [{education: 'Masters'}];
var target1 = [{dept: 'IT',education: ''}];
var employees = [
{id: 1,age: 35,name: 'James',dept: 'IT',education: 'Masters'},
{id: 2,age: 25,name: 'David',dept: 'Accounts',education: 'High School'},
{id: 3,age: 45,name: 'Tim',dept: 'HR',education: 'Graduate'},
{id: 4,age: 50,name: 'Vinod',dept: 'IT',education: 'PHD'},
{id: 5,age: 46,name: 'Matt',dept: 'IT',education: 'Masters'}
];
function findByKV(array0, array1, key, index = 0) {
var value = array1[index][key];
var array2 = array0.filter(function(obj) {
return Object.keys(obj).some(function(key) {
return obj[key].toString().indexOf(value) != -1;
});
});
return array2;
}
var result0 = findByKV(employees, target0, 'education');
var result1 = findByKV(employees, target1, 'dept');
console.log('Found targrt0: ' + JSON.stringify(result0, null, 2));
console.log('Found target1: ' + JSON.stringify(result1, null, 2));

Search for all values in array of objects

I have three arrays.
One of them contains values I will be testing. The two others are arrays of object which might include the values of my first array under the name key.
const myArray = ["foo", "bar"];
const testArray1 = [
{name: "foo"},
{name: "bar"},
{name: "something else"}
]
const testArray2 = [
{name: "foo"},
{name: "rab"},
{name: "something else"}
]
I am trying to write a condition which would return true only if the tested array contains all of the values of my first array.
With the same example it would give me something like this :
if (testArray1.containsAll(myArray)) // true
if (testArray2.containsAll(myArray)) // false
What is the best way to resolve this ?
Thanks, any help much appreciated
With array.prototype.every and array.prototype.find, it should be:
const myArray = ["foo", "bar"];
const testArray1 = [
{name: "foo"},
{name: "bar"},
{name: "something else"}
];
const testArray2 = [
{name: "foo"},
{name: "rab"},
{name: "something"}
];
console.log(myArray.every(s => testArray1.find(o => o.name === s)));
console.log(myArray.every(s => testArray2.find(o => o.name === s)));
can be use, every and some. these are return only true/false
const myArray = ["foo", "bar"];
const testArray1 = [
{name: "foo"},
{name: "bar"},
{name: "something else"}
]
const testArray2 = [
{name: "foo"},
{name: "rab"},
{name: "something else"}
]
let result1 = testArray1.every(item => myArray.some(array => item.name == array))
let result2 = testArray2.every(item => myArray.some(array => item.name == array))
console.log('result1', result1)
console.log('result2', result2)
Check this out. May not be the best way but works perfectly fine.
const myArray = ["foo", "bar"];
const testArray1 = [
{name: "foo"},
{name: "bar"},
{name: "something else"}
]
const testArray2 = [
{name: "foo"},
{name: "rab"},
{name: "something else"}
]
let aFlag = testArray1.filter( a => myArray.includes(a.name)).length === myArray.length;
let bFlag = testArray2.filter( a => myArray.includes(a.name)).length === myArray.length;
console.log(aFlag, bFlag)

unEven an array, like the concatAll function

I have this 2 Arrays representing the same data:
array1 = [
{name: "max", age: 30},
{name: "paul"},
{name: "paul.Jack", age: 25},
{name: "max.David"},
{name: "max.Sylvia", age: 27},
{name: "paul.Jack.Ned"},
{name: "paul.Jack.Mike"},
{name: "max.David.Jeff"},
{name: "max.Sylvia.Anna", age: 5},
{name: "max.David.Buffy"},
{name: "max.Sylvia.Craig"},
{name: "max.Sylvia.Robin"}
];
array2 = [
{
name: "max",
age: 30,
children: [
{
name: "Sylvia",
age: 27,
children: [
{name: "Anna", age: 5},
{name: "Craig"},
{name: "Robin"}
]
},
{
name: "David",
children: [
{name: "Jeff"},
{name: "Buffy"}
]
}
]
},
{
name: "paul",
children: [
{
name: "Jack",
age: 25,
children: [
{name: "Ned"},
{name: "Mike"}
]
}
]
}
];
my objective is to have a function unEven which transform the array1 to the array2, I'm using lodash to do this here's where I'm now:
To unEven array1 to array2 the tracking property in this case 'name' contain the information about where in the new array this item should be pushed check this js bin, this work for 3 level nested array but my goal is to have it unEven arrays without limit of their nesting level, that's where I'm stuck.
The unEven function will be like the concatAll function presented in this video.
Here's the unEven function:
Array.prototype.unEven = function (trackingProperty, children, resultArray) {
var newItem, prop, index, parent, subParent, subParentIndex;
resultArray = resultArray || [];
this.forEach(function (item) {
newItem = lodash.omit(item, trackingProperty);
prop = lodash.pick(item, trackingProperty);
if (prop[trackingProperty].indexOf('.') === -1) {
resultArray.push(item);
} else {
newItem[trackingProperty] = prop[trackingProperty].split(".");
parent = {};
parent[trackingProperty] = newItem[trackingProperty][0];
index = lodash.indexOf(resultArray, lodash.find(resultArray, parent));
if (newItem[trackingProperty].length === 2) {
newItem[trackingProperty] = newItem[trackingProperty][1];
if (!Array.isArray(resultArray[index][children])) {
resultArray[index][children] = [];
}
resultArray[index][children].push(newItem);
} else if (newItem[trackingProperty].length === 3) {
subParent = {};
subParent[trackingProperty] = newItem[trackingProperty][1];
subParentIndex = lodash.indexOf(resultArray[index][children], lodash.find(resultArray[index][children], subParent));
newItem[trackingProperty] = newItem[trackingProperty][2];
if (!Array.isArray(resultArray[index][children][subParentIndex][children])) {
resultArray[index][children][subParentIndex][children] = [];
}
resultArray[index][children][subParentIndex][children].push(newItem);
}
}
});
return resultArray;
};
To give my use case for this I'm trying to make a d3js tree layout of angular ui router in my application that will be generated from the routes JSON file since I make the routes in a JSON file.
Here's a lodash-heavy solution that I think does what you want. You can skip the cloning if you don't care about mutating the original array, and skip the sorting if you always have children after their parents in the original array.
function unEven(array1) {
_(_.clone(array1, true)) //begin chaining syntax, with cloned array
.each(function(person) {
person.name = person.name.split(".") //replace name with array of names
})
.sortBy(function(person) {return person.name.length}) //sort so that we handle children after parents
.reduce(function(result, person) {
var parentArray = result;
var name = person.name.pop() //their actual name is the last one in the list
_.each(person.name, function(parentName) { //loop through parent names to find the proper array to add to
var parent = _.find(parentArray, {name: parentName});
if(!parent) throw new Error(name + " has non-existent parent "+parentName);
parentArray = parent.children = parent.children || []
})
person.name = name; //return name back to just being their name
parentArray.push(person);
return result;
}, []) //reduce ends chaining syntax; so no need for .value
}

Categories