I thought my map and pluck functions are collection correct, but when I try to call pluck to get "type" of car object, it returns an empty array....? empty array...???
update: thanks for pointing out that it is object.....So I added for in in my map function, but seems not working? is anything wrong?
function map(collection,iterator){
var result=[];
if(Array.isArray(collection)){
for (var i=0;i<collection.length;i++){
result.push(iterator(collection[i]));
}
}else{
for (var key in collection){
result.push(iterator(collection[key]))};
}
return result;
};
function pluck(collection, key) {
return map(collection, function (value) {
return value[key]
});
}
var car = { type: "Fiat", model: "500", color: "white" };
console.log(pluck(car, function (auto) {
return auto.type;
}));
> the result: []
console.log(pluck(car, function (auto) {
return auto.type;
}));
should be
console.log(pluck(car, 'type'));
Also, car needs to be an array.
var car = [{ type: "Fiat", model: "500", color: "white" }];
You are passing this
var car = { type: "Fiat", model: "500", color: "white" };
While your map function expects array.
Use for-in loop if you want to pass object.
Pluck function only makes sense for arrays, because only arrays make sense to map. For objects you want to just read property:
var car = { type: "Fiat", model: "500", color: "white" };
console.log( car.type );
function map(collection, filter) {
var result = [];
for (var i = 0; i < collection.length; ++i) {
result.push(filter(collection[i]))
}
return result;
}
function pluck(collection, filter) {
return map(collection, filter);
}
var cars = [{type: "Fiat", model: "500", color: "white"}]
var result = pluck(cars, function(auto) {
return auto.type;
})
document.write(JSON.stringify(result))
because its an object, not array
Related
how to get the value in any way if key does match with "Item"
const data = [{
"Item-55566": "phone",
},
{
"Items-44555": "Case",
}
];
/* How to get value if index found by Item */
for(let i = 0; i<data.length; i++) {
console.log(data[i].includes("Item"));
//Expecting phone and case
}
for-in allows you to loop through the keys in an object. Not to be confused with for-of, which loop through elements in an array.
const data = [{
"Item-55566": "phone",
},
{
"Items-44555": "Case",
}
];
for(let datum of data)
{
for(let key in datum)
{
if(key.includes("Item"))
{
console.log(datum[key]);
}
}
}
In the simple way just change data[i].includes("Item") to data[i].keys().includes("Item").
BUT! Could we have some alternative data set here? For example:
const data = [{
"Item-55566": "phone",
"SomeKey: "Some Value",
123123: "Numeric key with value"
},
{
"Items-44555": "Case",
"Another-key": "Another value"
}
];
In this case you need to put some changes in your code to find correct keys & values:
for(let i = 0; i<data.length; i++) {
data[i].keys().forEach(v=>{
String(v).includes("Item") && console.log("Got index: ${i}, key: ${v}, value: ${data[i][v]}")
})
}
The for loop iterates through the two objects, so you can check to see whether the object has that particular property using hasOwnProperty()
const data = [
{
"Item-55566": "phone",
},
{
"Items-44555": "Case",
},
];
/* How to get value if index found by Item */
for (let i = 0; i < data.length; i++) {
if (data[i].hasOwnProperty("Item-55566")) {
console.log(data[i]);
}
}
If you want to keep your loop (good that it's only one loop compared to other answers) you can do it with Object.keys and values:
const data = [{
"Item-55566": "phone",
},
{
"Items-44555": "Case",
}
];
/* How to get value if index found by Item */
for(let i = 0; i<data.length; i++) {
if(Object.keys(data[i])[0].includes('Item')){
console.log(Object.values(data[i])[0]);
}
}
You can use .filter to filter all items of the data array which includes Item text.
Then you can use .map to render new value from each object comes from data array.
const data = [
{"Item-55566": "phone", },
{ "Items-44555": "Case",},
{ "Other-44555": "Nope",}];
var filteredItems = data.filter(item => Object.keys(item)[0].includes("Item"));
console.log(filteredItems.map(item => Object.values(item)[0]));
Refactor code - By using .reduce()
const data = [
{"Item-55566": "phone", },
{ "Items-44555": "Case",},
{ "Other-44555": "Nope",}];
var res = data.reduce((prev, curr) =>
{
var entries = Object.entries(curr)[0];
if(entries[0].includes("Item"))
prev.push(entries[1]);
return prev;
}, []);
console.log(res);
I have an array objArray. I want to make a function so that it will check if there is another object with the same name key. If it exists, it will add +1 in the qty key. If the object doesn't exist, it will push the new object to the array.
var objArray = [
{"name":"bike","color":"blue","qty":2},
{"name":"boat","color":"pink", "qty":1},
];
var carObj = {"name":"car","color":"red","qty":1};
var bikeObj = {"name":"bike","color":"blue","qty":1};
function checkAndAdd (obj) {
for (var i = 0; i < objArray.length; i++) {
if (objArray[i].name === obj.name) {
objArray[i].qty++;
break;
}
else {
objArray.push(obj);
}
};
}
checkAndAdd(carObj);
console.log(objArray);
checkAndAdd(bikeObj);
console.log(objArray);
After checkAndAdd(carObj);
console.log(objArray);
Should give
[
{"name":"car","color":"red", "qty":1},
{"name":"bike","color":"blue","qty":2},
{"name":"boat","color":"pink", "qty":1},
]
And fter checkAndAdd(bikeObj);
console.log(objArray);
Should give
[
{"name":"car","color":"red", "qty":1},
{"name":"bike","color":"blue","qty":3},
{"name":"boat","color":"pink", "qty":1},
]
Thanks in advance!
You need to check all objects and exit the function if one item is found for incrementing the quantity.
If not found push the object.
var objArray = [{ name: "bike", color: "blue", qty: 2 }, { name: "boat", color: "pink", qty: 1 }],
carObj = { name: "car", color: "red", qty: 1 },
bikeObj = { name: "bike", color: "blue", qty: 1 };
function checkAndAdd (obj) {
for (var i = 0; i < objArray.length; i++) {
if (objArray[i].name === obj.name) {
objArray[i].qty++;
return; // exit loop and function
}
}
objArray.push(obj);
}
checkAndAdd(carObj);
console.log(objArray);
checkAndAdd(bikeObj);
console.log(objArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }
The problem is that you're push()ing inside the loop, instead of returning immediately once found and only call push() outside the loop.
A cleaner approach would be:
function checkAndAdd(obj) {
var matchingObj = objArray.find(o => o.name === obj.name);
if (matchingObj)
matchingObj.qty++;
else
objArray.push(obj);
}
You can also use find to search for the object property.
Using Object.assign before pushing the object will clone the object and will not change the original object when you change the qty (If you add more object with the same name.)
var objArray = [
{"name":"bike","color":"blue","qty":2},
{"name":"boat","color":"pink", "qty":1},
];
var carObj = {"name":"car","color":"red","qty":1};
var bikeObj = {"name":"bike","color":"blue","qty":1};
function checkAndAdd(obj) {
let o = objArray.find(o => o.name === obj.name); //Find if name exist
if (!o) objArray.push(Object.assign({},obj)); //If not exist, push.
else o.qty += obj.qty; //If exist, add the qty
}
checkAndAdd(carObj);
console.log(objArray);
checkAndAdd(bikeObj);
console.log(objArray);
Use findIndex to find in objArray if the object exist.If it does then update the object else push the new object
var objArray = [{
"name": "bike",
"color": "blue",
"qty": 2
},
{
"name": "boat",
"color": "pink",
"qty": 1
},
];
var carObj = {
"name": "car",
"color": "red",
"qty": 1
};
var bikeObj = {
"name": "bike",
"color": "blue",
"qty": 1
};
function checkAndAdd(obj) {
var x = objArray.findIndex(function(item) {
return item.name === obj.name;
});
if (x === -1) {
objArray.push(obj)
} else {
objArray[x].qty = objArray[x].qty + obj.qty
}
}
checkAndAdd(carObj);
checkAndAdd(bikeObj);
console.log(objArray);
Simple enough:
function checkAndAdd(obj) {
for (var i=0; i < objArray.length; i++) {
if (objArray[i]name === obj.name) {
objArray[i].qty++;
return
}
}
objArray.push(obj)
}
Explanation:
Your function was pushing each time the object name didn't match. Instead, when this function a matching name, it incrementes the qty and stops and then if the loops ends without any match, it pushes the obj.
Say i have a collection of objects like so
var collection = [
{
name:"John",
age:12,
location:"Califonia",
gender:"Male"
},
{
name:"Jane",
age:18,
location:"New york",
gender:"Female"
}
]
it is obvious "location" is the object key with the longest character length.
But how can i get this dynamically as i dont know how collection will be structured in advance.
With these functions:
/**
* Get the longest key in an object.
*/
function longestKey(obj) {
return Object.keys(obj).reduce(function(all, current) {
return all.length > current.length ? all : current;
});
}
/**
* Get the object with the longest key from array of objects.
*/
function longestKeyObj(arr) {
return arr.reduce(function(all, current) {
return longestKey(all).length > longestKey(current).length ? all : current;
});
}
You can do:
const me = {
name: 'nabil',
occupation: 'programming',
dob: '1984-12-28',
};
const you = {
longestKey: 'blah!',
};
console.log('The object is: ', longestKeyObj([me, you]));
console.log('The key is: ', longestKey(longestKeyObj([me, you])));
Which outputs:
The object is: { longestKey: 'blah!' }
The key is: longestKey
Demo: https://repl.it/#kadimi/longestKey
if you are sure the items in the collection will always have the same structure you can simple do this.
var collection = [
{
name:"John",
age:12,
location:"Califonia",
gender:"Male"
},
{
name:"Jane",
age:18,
location:"New york",
gender:"Female"
}
]
function getMaxKeys(collection){
var keys = Object.keys(collection[0]);
var keyWithMaxWidth = keys.reduce(function(prev, current){
if(prev.length > current.length) return prev;
else return current
});
return keyWithMaxWidth;
}
getMaxKeys(collection) //location
you can get array object key of specific object by command :
Object.keys(<object>)
Make a loop for find longest key. In your problem you need loop for all object in array
The code below will solve your problem in optimal way:
var sorted = (Object.keys(collection[0])).sort(function(a, b){
return b.length - a.length;
});
sorted[0]; // Location
You can loop each object in the array and then loop each property in the object like so:
var collection = [
{
name:"John",
age:12,
location:"Califonia",
gender:"Male"
},
{
name:"Jane",
age:18,
location:"New york",
gender:"Female"
},
{
veryLong: "This key will definitely be the longest"
}
];
var stats = {
key: '',
valLen: 0
};
collection.forEach(function(obj){
for(var prop in obj){
if(obj[prop].length > stats.valLen){
stats.key = prop
stats.valLen = obj[prop].length
}
}
});
console.log(stats.key);
console.log(stats.valLen);
Each item in the array may have a different format.
This example will log: 'veryLong' as longest key and 39 as its length.
See this fiddle
Just loop through the keys with Object.keys(obj) and pick up the longest one, Use the following function:
var getLongestKey = function getLongestKey(obj) {
for (key in keys) {
if (keys[key].length > longest.length) {
longest = keys[key];
}
}
}
And this is a working demo, to get the longest key for all the objects in the array :
var collection = [{
name: "John",
age: 12,
location: "Califonia",
gender: "Male"
}, {
name: "Jane",
age: 18,
location: "New york",
gender: "Female"
}];
var getLongestKey = function getLongestKey(obj) {
for (key in keys) {
if (keys[key].length > longest.length) {
longest = keys[key];
}
}
}
for (i = 0; i < collection.length; i++) {
var obj = collection[i];
var keys = Object.keys(obj);
var longest = keys[0];
getLongestKey(obj);
alert("Longest key in Object " + i + " is : " + longest);
}
I have a list with that contains a list of objects. Each object has 4 properties on it. There is a checkbox list with the unique values of two of the properties, this helps build my filter array.
the Filter might end up looking like this:
[
{
prop: 'username',
val: ['max', 'sam']
},
{
prop: 'color',
val: ['blue', 'green']
}
]
The list of objects would look something like this:
[
{
username: 'sam',
color: 'blue'
},
{
username: 'jimmy',
color: 'blue'
},
{
username: 'sam',
color: 'black'
},
{
username: 'max',
color: 'green'
},
{
username: 'max',
color: 'blue'
}
]
The Desired Result
[
{
username: 'sam',
color: 'blue'
},
{
username: 'max',
color: 'green'
},
{
username: 'max',
color: 'blue'
}
]
I feel like I'm going down a never ending forEach rabbit hole. I'm guessing I need some sort of recursion. Currently here is what I have:
var temporary = scope.transactions;
function getFilteredTransactions() {
var filter = deviceFilterService.get();
if (filter.length > 0) {
var temp2 = [];
angular.forEach(filter, function (fil) {
//object
angular.forEach(fil.val, function (filterValue) {
//list on each object
angular.forEach(temporary, function (transaction) {
if (transaction[fil.prop] === filterValue) {
if (temp2.indexOf(transaction) === -1) {
temp2.push(transaction);
}
}
});
temporary = temp2;
});
});
$log.debug(temporary);
scope.transactions = temporary;
} else {
initialize();
}
}
This is starting to work, the second time it goes through the property for color it ends up just wanting to add the exact same transaction to the temp2 array. There has to be a better way to set this up, possibly through recursion.
If you convert the format of the first list to a dictionary, i think if should get easier.
var dict = {};
angular.forEach(source1, function(ob){
dict[ob.prop] = ob.val;
});
function getFiltered(ob){
for(var prop in ob){
if(dict[prop] && dict[prop].indexOf(ob[prop]) === -1){
return false;
}
}
return true;
};
and just call it as:
var temporary = scope.transactions.filter(getFiltered);
Demo
Basically the first part converts:
[
{
prop: 'username',
val: ['max', 'sam']
},
{
prop: 'color',
val: ['blue', 'green']
}
];
to:
{
username:['max', 'sam'],
color:['blue', 'green']
}
so that it makes the look up much easier.
You might want to change the variable names here for clarity, but this will do what you're asking for:
var values = {};
angular.forEach(startingData, function(rawData) {
angular.forEach(rawData, function(value, key) {
if (angular.isUndefined(values[key])) {
values[key] = [];
}
if (values[key].indexOf(value) === -1) {
values[key].push(value);
}
})
});
var result = [];
angular.forEach(values, function(value, key) {
result.push({prop: key, val: value})
});
You can simply iterate each key of the data the needs filtering, find the appropriate filter per that key, and check the value against the filter values:
$scope.transactions = $scope.transactions.filter(isItemValidFilter);
function isItemValidFilter(item) {
var filters = deviceFilterService.get();
//For each property in the data, get the correct filter from the list of filters
var totalConditions = Object.keys(item).length;
var correctConditions = 0;
for (var filterKey in item) {
var correctFilters = filters.filter(function(dataFilter) {
return dataFilter.prop == filterKey
});
if (correctFilters.length) {
//Ill assume only 1 filter, so just use the 0 index
var correctFilter = correctFilters[0];
var conditions = correctFilter.val;
if (conditions && conditions.length) {
//check the values!
if (conditions.indexOf(item[filterKey]) > -1) {
correctConditions++;
}
}
}
}
return correctConditions === totalConditions;
}
Demo: http://jsfiddle.net/Lz32hka5/1/
Try:
var temp2 = [], matched;
angular.forEach(temporary, function(item){
matched = true;
angular.forEach(Object.keys(item), function(key){
angular.forEach(filter, function(filter){
filter.prop == key && filter.val.indexOf(item[key]) == -1 && (matched = false);
});
});
matched && temp2.push(item);
});
console.log(temp2)
temporary is the list of objects, filter: your filters
Demo: http://jsfiddle.net/wZVanG/7wnae850/
If I have an array that looks like this;
markers[56] = { label: "One" };
markers[62] = { label: "Two" };
markers[87] = { label: "Three" };
markers[125] = { label: "Four" };
Now I have some JS;
for (var thisMarker in markers) {
//What goes here so I can access the "label" property?
}
I know this is simplistic but later on there will be many more properties added to the object not just "label".
I believe you can access it like this,
for (var thisMarker in markers) {
alert(markers[thisMarker].label);
}
for(var thisMarker in markers){
//this will give you the label- markers[thisMarker].label
}