I have 2 hashes(objects) for ex.
hash1 = {myKey: ["string1"]}
hash2 = {myKey: ["string2"]}
I want to merge them together, so in the end i would get something like following -
{myKey: ["string1", "string2"] }
I tried $.extend, but that doesnt work for arrays as property
You can take a function for that.
function add(o, v) {
Object.keys(v).forEach(function (k) {
o[k] = o[k] || [];
v[k].forEach(function (a) {
o[k].push(a);
});
});
}
var hash1 = { myKey: ["string1"] },
hash2 = { myKey: ["string2"] };
add(hash1, hash2);
document.write('<pre>' + JSON.stringify(hash1, 0, 4) + '</pre>');
Note: check the case sensitivity of your keys.
You can do something like this:
hash1 = {myKey: ["string1"]}
hash2 = {myKey: ["string2"]}
var result = {};
for (var hash1Key in hash1) {
if (hash1.hasOwnProperty(hash1Key)) {
for (var hash2Key in hash2) {
if (hash2.hasOwnProperty(hash2Key)) {
if (hash1Key === hash2Key) {
result[hash1Key] = [hash1[hash1Key], hash2[hash2Key]]
}
}
}
}
}
See it live in jsFiddle
You can Array.prototype.push.apply() to merge array
var hash1 = {myKey: ["string1"]};
var hash2 = {myKey: ["string1"]};
Array.prototype.push.apply(hash1.myKey, hash2.myKey)
console.log(hash1)
Related
I try to create an object with a value for the last key. I just have an Array with the keys and the value but dont know how it will be possible to create an object without use references in javascript.
As far as I know there isnt a way to create a reference of a variable in javascript.
This is what i have:
var value = 'test';
var keys = ['this', 'is', 'a', 'test'];
This is what i want:
myObject: {
this : {
is: {
a : {
test : 'test'
}
}
}
}
Any idea how i can do this the best way in JavaScript ?
How about this...
const value = 'test'
const keys = ['this', 'is', 'a', 'test']
const myObject = keys.reduceRight((p, c) => ({ [c]: p }), value)
console.info(myObject)
Or, if you're not a fan of object literal key shortcuts and arrow functions...
keys.reduceRight(function(p, c) {
var o = {};
o[c] = p;
return o;
}, value);
See Array.prototype.reduceRight() - Polyfill if you need IE <= 8 support.
With this:
var curObj = myObject = {};
for(var i=0; i<keys.length-1; i++)
curObj = curObj[keys[i]] = {};
curObj[value] = keys[i];
Outputs:
{
this : {
is: {
a : {
Test : 'test'
}
}
}
}
As opposed to the other answers, this outputs exactly what you asked for.
Cheers
var o={}, c=o;
var value = 'Test';
var keys = 'this is a test'.split(' ');
for (var i=0; i<keys.length-1; ++i) c = c[keys[i]] = {};
c[keys[i]] = value;
console.log(JSON.stringify(o));
// {"this":{"is":{"a":{"test":"Test"}}}}
If you want the output like
{
this : {
is: {
a : 'test'
}
}
}
Do the following
var keys = ['this', 'is', 'a', 'test'];
var output = keys.reduceRight((p,c)=>({[c]:p}))
console.log(output)
And the output will be like
{ this: { is: { a: 'test' } } }
Here is my requirement. I was able to achieve to some level in java but we need to move it to typescript (client side).
Note: The below input is for example purpose and may vary dynamically.
Input
var input = ["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"];
We need to create an utility function that takes above input and returns output as below.
Output:
Should be string not an object or anything else.
"{ a { name, type }, b { city {name, zip } , desc }, c }"
any help is much appreciated.
I don't see that typescript plays any role in your question, but here's a solution for constructing the string you requested. I first turn the array into an object with those properties, then have a function which can turn an object into a string formatted like you have
const input = ["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"];
const arrayToObject = (arr) => {
return arr.reduce((result, val) => {
const path = val.split('.');
let obj = result;
path.forEach(key => {
obj[key] = obj[key] || {};
obj = obj[key];
});
return result;
}, {});
}
const objectToString = (obj, name = '') => {
const keys = Object.keys(obj);
if (keys.length === 0) {
return name;
}
return `${name} { ${keys.map(k => objectToString(obj[k], k)).join(', ')} }`;
}
const arrayToString = arr => objectToString(arrayToObject(arr));
console.log(arrayToString(input));
Here's another variation. Trick is to parse the strings recursively and store the intermediate results in an Object.
function dotStringToObject(remainder, parent) {
if (remainder.indexOf('.') === -1) {
return parent[remainder] = true
} else {
var subs = remainder.split('.');
dotStringToObject(subs.slice(1).join('.'), (parent[subs[0]] || (parent[subs[0]] = {})))
}
}
var output = {};
["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"].forEach(function(entry) {
dotStringToObject(entry, output)
});
var res = JSON.stringify(output).replace(/\"/gi, ' ').replace(/\:|true/gi, '').replace(/\s,\s/gi, ', ');
console.log(res)
// Prints: { a { name, type }, b { city { name, zip }, desc }, c }
You could do something like this:
var input = ["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"];
var output = {};
for(var i =0; i < input.length; i+=2){
output[String.fromCharCode(i+97)] = {};
output[String.fromCharCode(i+97)].name = input[i];
output[String.fromCharCode(i+97)].type = input[i+1];
}
console.log(JSON.stringify(output));
I have one object that I had to take apart into two arrays to handle properly.
It looked like this:
{
city:"stuttgart",
street:"randomstreet",
...
}
Since it needs to fit a certain directive I had to convert it to:
[
{key:"city", value:"stuttgart"}
{key:"street", value:"randomstreet"},
...
]
for this I first used
var mapFromObjectWithIndex = function (array) {
return $.map(array, function(value, index) {
return [value];
});
};
var mapFromObjectWithValue = function (array) {
return $.map(array, function(value, index) {
return [index];
});
});
to create two arrays, one containing the old key, the other one is holding the old value. Then I created another, two dimensional array map them into a single array doing this
var mapToArray = function (arrayValue, arrayIndex) {
var tableData = [];
for (var i = 0; i<arrayIndex.length; i++){
tableData[i] = {key:arrayIndex[i] , value:arrayValue[i]};
}
return tableData;
};
(maybe I have already messed up by here, can this be done any easier?)
Now, I use the array (tableData) to display the data in a form. The value fields can be edited. In the end, I want to convert the array (tableData) to its original. (see first object)
Please note, that the original object doesn't only contain strings as values, but can also contain objects as well.
I think conversion can be definitely easier:
var obj = {
city:"stuttgart",
street:"randomstreet",
};
var tableData = Object.keys(obj).map(k => {return {key: k, value: obj[k]}});
console.log(tableData);
var dataBack = {};
tableData.forEach(o => dataBack[o.key] = o.value);
console.log(dataBack);
What do you want to do with objects? Do you want to expand them as well? If yes you can do something like this (and it works with nested objects as well):
var obj = {
city:"stuttgart",
street:"randomstreet",
obj: {a: 'a', b: 'b'},
subObject: {aha: {z: 'z', y: 'y'}}
};
function trasformToTableData(obj) {
if (typeof obj !== 'object') return obj;
return Object.keys(obj).map(k => {return {key: k, value: trasformToTableData(obj[k])}});
}
var tableData = trasformToTableData(obj);
console.log(tableData);
function transformBack(obj) {
if (Array.isArray(obj)) {
var support ={};
for (let i = 0; i < obj.length; i++) {
support[obj[i].key] = transformBack(obj[i].value)
}
return support;
}
return obj;
}
var dataBack = {};
tableData.forEach(o => dataBack[o.key] = transformBack(o.value));
console.log(dataBack);
Let's have some fun and turn our object into iterable to do the job as follows;
var input = {city:"stuttgart", street:"randomstreet", number: "42"};
output = [];
input[Symbol.iterator] = function*(){
var ok = Object.keys(this),
i = 0;
while (i < ok.length) yield {key : ok[i], value: this[ok[i++]]};
};
output = [...input];
console.log(output);
This function will map your object to an array when you call objVar.mapToArray(), by using Object.keys() and .map()
Object.prototype.mapToArray = function() {
return Object.keys(this).map(function(v) {
return { key: v, value: this[v] };
}.bind(this));
}
I would do something like this:
var dataObj = {
city:"stuttgart",
street:"randomstreet",
};
function toKeyValue(obj) {
var arr = [];
for (var key in obj) {
if(obj.hasOwnProperty(key)) {
arr.push({'key': key, 'value': obj[key]});
}
}
return arr;
}
var arrayKeyValue = toKeyValue(dataObj);
console.log(arrayKeyValue);
here is the situation. I got a an object contain lot of information, for example
var a = {
one:"foo",
two:"bar"
}
and now I want to provide and other object contained specify key. for example
var schema = {
two:""
}
then just create a new object base on key of schema
here , I would like to use lodash / moutjs or any lib
sorry for poor eng
With lodash you can _.pick() the schema _.keys() from the originalObj (the one you named a):
const originalObj = { one: "foo", two: "bar" }
const schema = { two: "" }
const result = _.pick(originalObj, _.keys(schema))
console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>
If you want pure JS, you can reduce the schema Object.keys():
const originalObj = { one: "foo", two: "bar" }
const schema = { two: "" }
const result = Object.keys(schema)
.reduce((obj, key) =>
originalObj.hasOwnProperty(key) ? { ...obj, [key]: originalObj[key] } : obj
, {})
console.log(result)
You don't need a library for a that simple operation. Here's a working code:
var copyObject = function(origin, keys) {
var destination = {};
for (var i = keys.length - 1; i >= 0; i--) {
if(origin.hasOwnProperty(keys[i])) {
destination[keys[i]] = origin[keys[i]];
}
};
return destination;
};
var a = {
one:"foo",
two:"bar"
};
var schema = copyObject(a, ['two']);
I don't sure that I understood you correctly. But, for example, you can use pick in underscore.
var a = {
one:"foo",
two:"bar"
}
var schema = _.pick(a, "two"); // returns {two: "foo")
Note, that also working in lodash.
var copyObject = function(origin, keys) {
var destination = {};
for (var i = keys.length - 1; i >= 0; i--) {
if(origin.hasOwnProperty(keys[i])) {
destination[keys[i]] = origin[keys[i]];
}
};
return destination;
};
var a = {
one:"foo",
two:"bar"
};
var schema = copyObject(a, ['two']);
I am trying to change object key names to something different. Like "name => text, _id => value"
I tried the following which works fine. I was wondering whether there is better ways to do that?
var a = {
name: "Foo",
_id: "1234"
};
var b = {
name: "bar",
_id: "222"
};
var map = {
name: "text",
_id: "value",
};
var arr = [a, b];
var arr2 = [];
_.each(arr, function (obj) {
obj = _.reduce(a, function (result, value, key) {
key = map[key] || key;
result[key] = value;
return result;
}, {});
arr2.push(obj);
});
console.log(arr2);
JSFiddle
If the number of properties are only two, you can map them manually.
var arr2 = _.map(arr, function (e) {
var o = {};
o[map.name] = e.name;
o[map._id] = e._id;
return o;
});
Sometimes, do it manually is cleaner.
If you want to iterate over the properties of given objects, then:
var arr2 = _.map(arr, function (e) {
var o = {};
for (k in e) {
o[k] = e[k];
}
return o;
});
Those codes are shorter and more readable than the original ones.