I have a list of key-value pairs and I am trying to store the key N times in another array.
I'm struggling with the logic, if I iterate over the list_of_objects I can't see a way to keep track of which keys-values have already been assigned.
var kv={"a":2,"b":1,"c":1};
var list_of_objects=[bob,bill,jane,joe];//these are objects
GOAL
bob.kv="a"
bill.kv="a"
jane.kv="b"
joe.kv="c"
Notes in response to comment: kv is a property of the object bob (or bill, or jane, or joe)
You might want to try Object.keys()
Object.keys(kv).forEach(function(key) {
var val = kv[key];
while(val-- > 0) {
var obj = objects.shift();
obj.kv = key;
console.log(obj)
}
});
Similar to #MatUtter's answer but does not mutate the list_of_objects array:
var index = 0;
for (var key in kv) {
if (kv.hasOwnProperty(key)) {
var val = kv[key];
while (val-- > 0) {
list_of_objects[index].kv = key;
index++;
}
}
}
I'm trying to create a javascript class with a couple of methods that would let me add view and delete. I'm stuck with the add method, it should return me a unique ID of each string passed into the add method, but instead I can't figure out how to jump to a next code block when I'm done adding strings. Below is some of my current code:
var obj = {};
var arr = [];
var Words = function(){
this.add = function(newWord){
if(newWord !== false){
arr.push(newWord);
} else {
for (var i = 0; i < arr.length; i++){
obj[i] = arr[i];
return obj[i];
}
}
var words = new Words();
words.add('first');
words.add('second');
words.add('third');
I feel I should be creating a next() function of some sort that runs after I'm done pushing the last passed string, but I seem to have forgotten everything.
While I don't really know what you're trying to accomplish, there are some problems with your code...
An Object has keys and values. For every key there is a value.
Ex. mykey: "corresponding value"
for (var i = 0; i < arr.length; i++){
obj[i] = arr[i];
return obj[i];
}
You are setting obj[i] when i is an integer, so unless your keys are integers (probably not), you need to specify keys.
Otherwise, use another array for what you are doing (if possible).
If you are actually filling this object with keys that are numerals, then ignore the above.
I would also point you to using callbacks for finding out when .add() is finished (or just run your code after running .add() ??).
Why not just create an array, set it's values as you want, and retrieve them based on iteration?
var array = [];
//add
array.push("first");
//view value
console.log(array[0]); // output: "first"
//view index
array.indexOf("first"); // output 0
//delete
array.splice(0, 1);
Then wrap this as a class if you'd like:
var array = [];
var Words = function() {
this.add = function(input) {
array.push(input);
}
this.view = function(input) {
return array[input];
}
this.delete = function(input) {
array.splice(input, 1);
}
}
Hope this helps.
I'm in a situation where I need to store some data in an object, but I can only have a set number of that data due to browser limitations. Since my app also needs to be able to get this data, I am storing it in an object where the keys of the properties are identifiers.
The data looks like this:
memory = {
13: {
last_updated: 241,
...
},
26: {
last_updated: 363,
....
}
}
last_updated would be a Date.now() string of course. This object can not have more than 6 properties. When it reaches that length, I need to start replacing the oldest properties with new data. How do I get the oldest property of the object?
One way would be to just sort the objects keys by the last updated timestamp, and pop of the last one, the oldest one
var oldest = memory[Object.keys(memory).sort(function(a,b) {
return memory[b].last_updated - memory[a].last_updated
}).pop()];
You can do something like this:
var obj = {};
for(var i = 0;i < 5; i++){
obj[i] = {date:Date.now() + i};
}
function addNew(date){
if(obj.length < 5){
obj[obj.length] = {date:date};
return;
}
var arr = [];
for(var prop in obj){
arr.push({prop:prop,date:obj[prop].date})
}
var last = arr.sort(function(a, b){return b.date-a.date})[0].prop;
obj[last].date = date;
}
addNew(Date.now() + 100);
console.log(obj);
You need to add new properties to the object only by using the addNew(...) function in order for this to work.
This would take the newest 6 items from the memory object.
var freshMemory = Object.keys(memory)
.map(function (k) { return [k, data[k]] })
.sort(function (a, b) { return b[1].last_updated - a[1].last_updated; })
.slice(0, 6)
.reduce(function (o, v) { o[v[0]] = v[1]; return o; }, {});
A short explanation
The Object.keys combined with the .map method will transfer the object to an array containing two-tuples (the key and the value)
then the .sort will sort the array by last_updated in reverse order
then the .slice will take the first 6 items
and finally .reduce will convert the array with two-tuples back to an object.
I have this object:
key = {
spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
wall:{type:2,img:app.assets.get('assets/wall.svg')},
grass:{type:3,img:app.assets.get('assets/grass.svg')},
spike:{type:4,img:app.assets.get('assets/spike.svg')},
ground:{type:5,img:app.assets.get('assets/ground.svg')}
};
And I have an array with only types and I need to add the given image to it, the array looks something like this:
[{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}]
Basically I want to loop the array, find the type in the key object and get the given image and save it into the array.
Is there any simple way to do this?
One thing that stands out here for me is the line
...get the given image and save it into the array
I'm assuming this means the original array. I think a better approach would be to map the appropriate keys and values to a new array but I've assumed, for this example, that it's a requirement.
In an attempt to keep the solution as terse as possible and the request for a lodash solution:
_.each(key, function(prop){
_.each(_.filter(types, { type: prop.type }), function(type) { type.image = prop.img });
});
Given the object of keys and an array of objects like so:
var key = {
spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
wall:{type:2,img:app.assets.get('assets/wall.svg')},
grass:{type:3,img:app.assets.get('assets/grass.svg')},
spike:{type:4,img:app.assets.get('assets/spike.svg')},
ground:{type:5,img:app.assets.get('assets/ground.svg')}
};
var arr = [{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}];
We can first create an array of the properties in the object key to make iterating it simpler.
Then loop over the array arr, and upon each member, check with a some loop which image belongs to the member by its type (some returning on the first true and ending the loop).
You can change the forEach to a map (and assign the returned new array to arr or a new variable) if you want the loop to be without side-effects, and not to mutate the original array.
var keyTypes = Object.keys(key);
arr.forEach(function (item) {
keyTypes.some(function (keyType) {
if (key[keyType].type === item.type) {
item.image = key[keyType].img;
return true;
}
return false;
});
});
The smarter thing would be to change the object of the imagetypes so that you could use the type as the accessing property, or create another object for that (as pointed out in another answer).
I'm not sure if this solution is modern, but it does not use any loops or recursion.
object = {
spawn: {type:1, img:app.assets.get('assets/spawn.svg')},
wall: {type:2, img:app.assets.get('assets/wall.svg')},
grass: {type:3, img:app.assets.get('assets/grass.svg')},
spike: {type:4, img:app.assets.get('assets/spike.svg')},
ground: {type:5, img:app.assets.get('assets/ground.svg')}
};
arr = [
{type:1, image:null},
{type:3, image:null},
{type:2, image:null},
{type:2, image:null},
{type:5, image:null}
];
var typeImages = {};
Object.getOwnPropertyNames(object).forEach(function(value){
typeImages[object[value].type] = object[value].img;
});
arr = arr.map(function(value){
return {
type: value.type,
image: typeImages[value.type]
};
});
var key = {
spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
wall:{type:2,img:app.assets.get('assets/wall.svg')},
grass:{type:3,img:app.assets.get('assets/grass.svg')},
spike:{type:4,img:app.assets.get('assets/spike.svg')},
ground:{type:5,img:app.assets.get('assets/ground.svg')}
};
var typesArray = [{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}];
for(var i = 0, j = typesArray.length; i < j; i++)
{
typesArray[i].image = getKeyObjectFromType(typesArray[i].type).img;
}
function getKeyObjectFromType(type)
{
for(var k in key)
{
if(key[k].type == type)
{
return key[k];
}
}
return {};
}
for (var i = 0; i < typesArray.length; i++) {
for (prop in key) {
if (key[prop].type === typesArray[i].type) {
typesArray[i].image = key[prop].img;
}
}
}
It loops through the array ("typesArray"), and for each array item, it go through all the objects in key looking for the one with the same "type". When it finds it, it takes that key object's "img" and saves into the array.
Using lodash (https://lodash.com/):
var key = {
spawn:{type:1,img:app.assets.get('assets/spawn.svg')},
wall:{type:2,img:app.assets.get('assets/wall.svg')},
grass:{type:3,img:app.assets.get('assets/grass.svg')},
spike:{type:4,img:app.assets.get('assets/spike.svg')},
ground:{type:5,img:app.assets.get('assets/ground.svg')}
};
var initialList = [{type:1,image:null},{type:3,image:null},{type:2,image:null},{type:2,image:null},{type:5,image:null}];
var updatedList = _.transform(initialList, function(result, item) {
item.image = _.find(key, _.matchesProperty('type', item.type)).img;
result.push(item);
});
This will go over every item in the initialList, find the object that matched their type property in key and put it in the image property.
The end result will be in updatedList
My JSON is below. It contains two Objects, each with a few key value pairs. How can I search through the entire JSON array and pull the object that contains a particular string as a value?
In this case, I need to pull the object with the coupon_code: COUPON1, so that I can then pull the ID of that Coupon.
In short, I just need to get the id of the Coupon with coupon_code: COUPON1
[Object, Object]
0: Object
coupon_code: "COUPON1"
created_at: "2013-06-04T13:50:20Z"
deal_program_id: 1
id: 7
updated_at: "2013-06-04T13:50:20Z"
__proto__: Object
1: Object
coupon_code: "COUPON3"
created_at: "2013-06-04T15:47:14Z"
deal_program_id: 1
id: 8
updated_at: "2013-06-04T15:47:14Z"
Thanks :)
You just loop through the array and look. There are lots of ways to do that in JavaScript.
E.g.:
var a = /*...your array...*/;
var index = 0;
var found;
var entry;
for (index = 0; index < a.length; ++index) {
entry = a[index];
if (entry.coupon_code == "COUPON1") {
found = entry;
break;
}
}
Or using ES5's Array#some method (which is one that can be "shimmed" for browsers that don't yet have it, search for "es5 shim"):
var a = /*...your array...*/;
var found;
a.some(function(entry) {
if (entry.coupon_code == "COUPON1") {
found = entry;
return true;
}
});
Write a generic find function :
function find (arr, key, val) { // Find array element which has a key value of val
for (var ai, i = arr.length; i--;)
if ((ai = arr[i]) && ai[key] == val)
return ai;
return null;
}
Call as follows :
find (arr, 'coupon_code', 'COUPON1')
var result = null;
Objects.forEach(function(obj, i){
if(obj.cupon_code == 'COUPON1'){
return result = obj;
}
});
console.log(result);
This will loop through your Array and check the coupon_code for your specified value. If it found something, it will return it in result.
Note that Array.forEach is available since JavaScript 1.6. You might want to take a look at which browser are supporting it.