I've taken the following sample from a different question. And I am able to identify the object. But I also need to find our the position of that object. For example:
var arr = [{
Id: 1,
Categories: [{
Id: 1
},
{
Id: 2
},
]
},
{
Id: 2,
Categories: [{
Id: 100
},
{
Id: 200
},
]
}
]
If I want to find the object by the Id of the Categories, I can use the following:
var matches = [];
var needle = 100; // what to look for
arr.forEach(function(e) {
matches = matches.concat(e.Categories.filter(function(c) {
return (c.Id === needle);
}));
});
However, I also need to know the position of the object in the array. For example, if we are looking for object with Id = 100, then the above code will find the object, but how do I find that it's the second object in the main array, and the first object in the Categories array?
Thanks!
Well, if every object is unique (only in one of the categories), you can simply iterate over everything.
var arr = [{
Id: 1,
Categories: [{Id: 1},{Id: 2}]
},
{
Id: 2,
Categories: [{Id: 100},{Id: 200}]
}
];
var needle = 100;
var i = 0;
var j = 0;
arr.forEach(function(c) {
c.Categories.forEach(function(e) {
if(e.Id === needle) {
console.log("Entry is in position " + i + " of the categories and in position " + j + " in its category.");
}
j++;
});
j = 0;
i++;
});
function findInArray(needle /*object*/, haystack /*array of object*/){
let out = [];
for(let i = 0; i < haystack.lenght; i++) {
if(haystack[i].property == needle.property) {
out = {pos: i, obj: haystack[i]};
}
}
return out;
}
if you need the position and have to filter over an property of the object you can use a simple for loop. in this sample your result is an array of new object because there can be more mathches than 1 on the value of the property.
i hope it helps
Iterate over the array and set index in object where match found
var categoryGroups = [{
Id : 1,
Categories : [{
Id : 1
}, {
Id : 2
},
]
}, {
Id : 2,
Categories : [{
Id : 100
}, {
Id : 200
},
]
}
]
var filterVal = [];
var needle = 100;
for (var i = 0; i < categoryGroups.length; i++) {
var subCategory = categoryGroups[i]['Categories'];
for (var j = 0; j < subCategory.length; j++) {
if (subCategory[j]['Id'] == findId) {
filterVal.push({
catIndex : i,
subCatIndex : j,
id : needle
});
}
}
}
console.log(filterVal);
Here is solution using reduce:
var arr = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 }, ] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }, ] } ]
const findPositions = (id) => arr.reduce((r,c,i) => {
let indx = c.Categories.findIndex(({Id}) => Id == id)
return indx >=0 ? {mainIndex: i, categoryIndex: indx} : r
}, {})
console.log(findPositions(100)) // {mainIndex: 1, categoryIndex: 0}
console.log(findPositions(1)) // {mainIndex: 0, categoryIndex: 0}
console.log(findPositions(200)) // {mainIndex: 1, categoryIndex: 1}
console.log(findPositions(0)) // {}
Beside the given answers with fixt depth searh, you could take an recursive approach by checking the Categories property for nested structures.
function getPath(array, target) {
var path;
array.some(({ Id, Categories = [] }) => {
var temp;
if (Id === target) {
path = [Id];
return true;
}
temp = getPath(Categories, target);
if (temp) {
path = [Id, ...temp];
return true;
}
});
return path;
}
var array = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 },] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }] }];
console.log(getPath(array, 100));
.as-console-wrapper { max-height: 100% !important; top: 0; }
I have an 'item' object in JavaScript, and the item can have settings like
color, size, etc.
I need to get all possible combinations in an array.
So lets say we have an item that looks like this:
var newItem = {
name: 'new item',
Settings: [
{name: 'color', values: ['green', 'blue', 'red']},
{name: 'size', values: ['15', '18', '22']},
{name: 'gender',values: ['male', 'female']}
]
};
I need to somehow get this:
[
[{SettingName:'color',value:'green'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'green'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'green'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'male'}],
[{SettingName:'color',value:'green'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'15'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'green'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'18'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'green'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'blue'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'female'}],
[{SettingName:'color',value:'red'},{SettingName:'size',value:'22'},{SettingName:'gender',value:'female'}]
]
This can be a good interview question.
See JS Bin for running example.
getAllPermutations(newItem);
function getAllPermutations(item) {
var permutations = [];
getAllPermutations0(item, permutations, []);
console.log(permutations);
}
function getAllPermutations0(item, permutations, array) {
if (array && array.length === item.Settings.length) {
permutations.push(array.slice()); // The slice clone the array
return;
}
var index = array.length;
var setting = item.Settings[index];
for (var i = 0; i < setting.values.length; i++) {
if (index === 0)
array = [];
var currValue = setting.values[i];
array.push({
SettingName: setting.name,
value: currValue
});
getAllPermutations0(item, permutations, array);
array.pop(); // pop the old one first
}
}
Here is a none recursive solution. It takes an empty or existing settings "matrix" and a values array, and return a new matrix as a combination of existing matrix content cloned for each new value, appended with pairs of new value setting items.
[A] -> [1,2] gives [A][1][A][2]
[A][1][A][2] -> [X,Y] gives [A][1][X][A][2][Y][A][2][X][A][1][Y]
and so on
function processSettings(settings, name, values) {
if (settings.length == 0) {
values.forEach(function(value) {
settings.push( [{ SettingName: name, value: value }] )
})
} else {
var oldSettings = JSON.parse(JSON.stringify(settings)), settings = [], temp, i = 0
for (i; i<values.length; i++) {
temp = JSON.parse(JSON.stringify(oldSettings))
temp.forEach(function(setting) {
setting.push( { SettingName: name, value: values[i] } )
settings.push(setting)
})
}
}
return settings
}
You can now create the desired settings literal this way :
var settings = []
for (var i=0; i<newItem.Settings.length; i++) {
var item = newItem.Settings[i]
settings = processSettings(settings, item.name, item.values)
}
demo -> http://jsfiddle.net/b4ck98mf/
The above produces this :
[
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"male"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"15"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"18"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"green"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"blue"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"female"}],
[{"SettingName":"color","value":"red"},{"SettingName":"size","value":"22"},{"SettingName":"gender","value":"female"}]
]
You can use Array.prototype.map(), for loop, while loop, Array.prototype.concat(). Iterate gender values; select each of color, size value in succession beginning at index 0 of either; iterating the furthest adjacent array from current gender, increment the index of the closest adjacent array; merge the resulting two gender arrays to form a single array containing all combinations of gender, color, size
var colors = newItem.Settings[0].values;
var sizes = newItem.Settings[1].values;
var gen = newItem.Settings[2].values;
var i = sizes.length;
var res = [].concat.apply([], gen.map(function(value, key) {
var next = -1;
var arr = [];
for (var curr = 0; curr < i; curr++) {
while (next < i - 1) {
arr.push([{
SettingName: "gender",
value: value
}, {
SettingName: "size",
value: sizes[curr]
}, {
SettingName: "color",
value: colors[++next]
}])
}
next = -1;
}
return arr
}))
var newItem = {
"name": "new item",
"Settings": [{
"name": "color",
"values": [
"green",
"blue",
"red"
]
}, {
"name": "size",
"values": [
"15",
"18",
"22"
]
}, {
"name": "gender",
"values": [
"male",
"female"
]
}]
}
var colors = newItem.Settings[0].values;
var sizes = newItem.Settings[1].values;
var gen = newItem.Settings[2].values;
var i = sizes.length;
var res = [].concat.apply([], gen.map(function(value, key) {
var next = -1;
var arr = [];
for (var curr = 0; curr < i; curr++) {
while (next < i - 1) {
arr.push([{
SettingName: "gender",
value: value
}, {
SettingName: "size",
value: sizes[curr]
}, {
SettingName: "color",
value: colors[++next]
}])
}
next = -1;
}
return arr
}))
document.querySelector("pre").textContent = JSON.stringify(res, null, 2)
<pre></pre>
plnkr http://plnkr.co/edit/C2fOJpfwOrlBwHLQ2izh?p=preview
An approach using Array.prototype.reduce(), Array.prototype.sort(), Object.keys(), for loop, while loop
var newItem = {
name: 'new item',
Settings: [
{
name: 'color',
values: ['green', 'blue', 'red']
},
{
name: 'size',
values: ['15', '18', '22']
},
{
name: 'gender',
values: ['male', 'female']
}
]
};
var props = ["SettingName", "value"];
var settings = newItem.Settings;
function p(settings, props) {
var data = settings.reduce(function(res, setting, index) {
var name = setting.name;
var obj = {};
obj[name] = setting.values;
res.push(obj);
return res.length < index ? res : res.sort(function(a, b) {
return a[Object.keys(a)[0]].length - b[Object.keys(b)[0]].length
})
}, []);
var key = data.splice(0, 1)[0];
return [].concat.apply([], key[Object.keys(key)].map(function(value, index) {
return data.reduce(function(v, k) {
var keys = [v, k].map(function(obj) {
return Object.keys(obj)[0]
});
var i = Math.max.apply(Math, [v[keys[0]].length, k[keys[1]].length]);
var next = -1;
var arr = [];
for (var curr = 0; curr < i; curr++) {
while (next < i - 1) {
var a = {};
a[props[0]] = keys[0];
a[props[1]] = v[keys[0]][++next];
var b = {};
b[props[0]] = keys[1];
b[props[1]] = k[keys[1]][next];
var c = {};
c[props[0]] = Object.keys(key)[0];
c[props[1]] = value;
arr.push([a, b, c]);
};
next = -1;
}
return arr
});
}));
}
document.querySelector("pre").textContent = JSON.stringify(
p(settings, props), null, 2
);
<pre></pre>
How can I get the values from this associative array in JavaScript?
I just need the email addresses and not the labels.
(
{
office = ("my#email.com");
home = ("ahome#anotheremail.com");
work = ("nothing#email.com");
},
{
home = ("test#test.se");
}
)
UPDATE: Prefered output in JSON would be:
{
"data": [
{
"email": "my#email.com"
},
{
"email": "ahome#anotheremail.com"
},
{
"email": "nothing#email.com"
},
{
"email": "test#test.se"
}
]
}
Thankful for all input!
What you probably meant to do is:
var x = [{
office: ("my#email.com"),
home: ("ahome#anotheremail.com"),
work: ("nothing#email.com")
},
{
home: ("test#test.se")
}]
and:
for(var j = 0; j < x.length; j++)
{
for(var anItem in x[j])
{
console.log(x[j][anItem])
}
}
// EDIT:
however, it's not the best practice to use for … in.
Maybe you could change your data structure to:
var x = [[{
value: "my#email.com",
type: "office"
},
{
value: "ahome#anotheremail.com",
type: "home"
},
{
value: "nothing#email.com",
type: "work"
}],
[{
value: "test#test.se",
type: "home"
}]];
and iterate over using:
for( var i = 0, xlength = x.length; i < xlength; i++ )
{
for( var j=0, ylength = x[i].length; j < ylength; j++ )
{
console.log(x[i][j].value);
}
}
Here's a one-liner:
console.log(Object.keys(assoc).map(k => assoc[k]));
where assoc is your associative array.
Edit
I have a better answer here.
You can 'foreach' over the object to get it's properties:
for(var j = 0; j < mySet.length; j++)
{
for(var propName in mySet[j])
{
var emailAddress = mySet[j][propName];
// Do Stuff
}
}
Answer for edited question:
var ret = {data: []};
for(var j = 0; j < x.length; j++)
{
for(var anItem in x[j])
{
ret.data.push({
email: x[j][anItem]
});
}
}
console.log(ret);
The result is kept in ret.
Is it your input in JSON format? Because if so, it's the wrong syntax. However
let _in = [
{
office : "my#email.com",
home : "ahome#anotheremail.com",
work : "nothing#email.com",
},
{
home : "test#test.se"
}
]
let _out = []
_in.forEach( record => {
_out = _out.concat(Object.values(record).map(x => new Object({email : x})))
})
console.log(_out)
for each record I extracted values and "packed" into an object with the "email" attrbiute, then I merged all those arrays obtained from the original array of records
It seems that you're looking for Object.values.