Convert Javascript Array to JSON User Defined Key/Value Pair - javascript

I need to take a string from a text input and convert it from an array to a JSON object.
let orderInputArray = ["key1", "value1", "key2", "value2"];
let json = {}
let key,value;
orderInputArray.forEach(function(keyValue) {
json[key] = keyValue.value;
});
let orderInputJSON = JSON.stringify(orderInputArray);
I need it to look like:
[{"key1": "value1"}, {"key2": "value2"}]
I'm not quite sure how to do this with the for each loop. Can anyone shed some light?

This is not the ideal way to create an object, but you can skip the key, create an object with the key/value using the current index (i), and push it to the result (orderInputObjects):
const orderInputArray = ["key1", "value1", "key2", "value2"];
const orderInputObjects = [];
orderInputArray.forEach(function(v, i, a) {
if(i % 2) orderInputObjects.push({ [a[i - 1]]: v });
});
console.log(orderInputObjects);

You can use a simple for loop and increment by 2 instead of 1
function arrayToKeyValue(array) {
let updated = [];
for (let i = 0; i < array.length; i += 2) {
const key = array[i];
const value = array[i + 1];
updated.push({ key: value });
}
return updated;
}

forEach uses a call back function, therefore it is not guaranteed to finish before the let orderInputJSON = JSON.stringify(orderInputArray); in your code.
Try using
var i;
for (i =0; i < orderInputArray.length; i=i+2){
//create object here using orderInputArray[i] as key and orderInputArray[i+1] as value
}

You can use filter to create an array of odd and even , then use reduce function to create the array of object
let orderInputArray = ["key1", "value1", "key2", "value2"];
let vals = orderInputArray.filter(function(item, index) {
return index % 2 === 1
});
let keys = orderInputArray.filter(function(item, index) {
return index % 2 === 0
}).reduce(function(acc, curr, index) {
acc.push({
[curr]: vals[index]
})
return acc
}, []);
console.log(keys)

You can do this with reduce as well
let orderInputArray = ["key1", "value1", "key2", "value2"];
var l = orderInputArray.length;
var jsobj = orderInputArray.reduce(function(acc, v, i) {
var o = {};
if (i % 2 === 0 && i < l - 1) {
o[v] = orderInputArray[i + 1];
acc.push(o)
}
return acc;
}, []);
console.log(JSON.stringify(jsobj))

Here my solution with splice:
var fruits = ["Banana", "Orange", "Apple", "Mango"];
var json = {};
while(fruits.length > 0){
let a = fruits.splice(0,2)
console.log(a)
json[a[0]] = a[1]
}
console.log(json)

let orderInputArray = ["key1", "value1", "key2", "value2"];
jsonArray = [];
orderInputArray.forEach((item, i, a)=> {if(i%2 === 0) jsonArray.push({item:a[i+1]})});
console.log(jsonArray)

Related

How to pass array values as an object prop dynamicly?

I need to treat array values as props of object. For example:
let arr = ['masa_icerik', 'urunler', 0, 'urun_adet'];
let obj = {
"_id": "5c13bd566704aa5e372dddcf",
"masa_id": 3,
"masa_numara": 3,
"masa_magaza": 1,
"masa_icon": "kola",
"masa_adi": "salon 3",
"masa_durum": 1,
"masa_icerik": {
"adisyon": "J1554745811908",
"urunler": [{
"urun_adet": 14,
"urun_fiyat": 3,
"urun_id": "5c16686b93d7b79ae6367864",
"urun_odenen": 0
}, {
"urun_adet": 1,
"urun_fiyat": 5,
"urun_id": "5c16686b93d7b79ae6367865",
"urun_odenen": 0
}]
},
"masa_acilis": "2019-04-08T17:50:12.052Z",
"masa_acan": "5c1eda01d1f4773110dd6ada"
};
I have an array and an object like above and I want to do something like this:
let res;
arr.forEach(elem => {
res = obj[elem];
});
and after that I need to get something like :
obj['masa_icerik']['urunler'][0]['urun_adet']
The number of the values is dynamic from server. Thats why i need something like this. Is there any way to do that? I need to change that property and return the changed obj.
You can use forEach loop to loop thru the array and store it to a temp variable. If all elements exist, it will change the value.
let arr = ['a', 'b', 'c'];
let obj = {'a':{'b':{'c':1}}};
let newValue = "NEW VALUE";
let temp = obj;
arr.forEach((o, i) => {
if (i < arr.length - 1) temp = temp[o] || null;
else if (temp !== null && typeof temp === "object" ) temp[o] = newValue;
});
console.log(obj);
If there are multiple multiple object properties missing in the last part of the array.
let arr = ['a', 'b', 'c', 'd'];
let obj = {'a': {'b': {}}};
let newValue = "NEW VALUE";
let temp = obj;
arr.forEach((o, i) => {
if (i < arr.length - 1) {
if (!temp[o]) temp[o] = {[arr[i + 1]]: {}};
temp = temp[o];
} else if (temp !== null && typeof temp === "object") temp[o] = newValue;
});
console.log(obj);
You can use references
Here idea is
Initialize val with object reference
Loop through array and keep setting new reference to val
let arr = ['a','b','c'];
let obj = {'a':{'b':{'c':1}}};
let getMeValue = (arr) => {
let val=obj;
arr.forEach(e => val = val && val[e] )
return val
}
console.log(getMeValue(arr))
console.log(getMeValue([1,2,3]))
UPDATE: I want to change values
let arr = ['a','b','c'];
let obj = {'a':{'b':{'c':1}}};
let getMeValue = (arr) => {
let val = obj
arr.forEach((e,i) => {
if(i === arr.length-1 && val){
val[e] = 5
}
else {
val = val && val[e]
}
})
return obj
}
console.log(getMeValue(arr))
I am not fully understanding where you are getting the new values from but I think this will get you on the right track.
let newObj = {};
arr.map(each => {
newObj[each] = "new value";
})
console.log(newObj);
I'm not sure about your requirment here, I guess you want the below:
let func = (arr, value)=>{
r = {};
r[arr[arr.length-1]] = value;
for(let i = arr.length-2; i>=0; i--){
obj = {};
obj[arr[i]] = r;
r = obj;
}
return r;
}
console.log(func(['a', 'b', 'c'], 1));

Convert String Into Delimited Object Key

I am trying to convert a string into a delimited object key but I need some assistance on how to iterate over the length of the array and join accordingly.
SET('my.delimited.string.of.unknown.length')
const SET = key => (state, val) => {
if(key.indexOf('.') !== -1) {
let array = key.split(".")
for (var i = 0; i < array.length; i++) {
// what should I do here?
}
// desired output based on array length
// state[ array[0] ][ array[1] ] = val
// state.my.delimited.string.of.unknown.length = val
}
}
One of those very rare usecases for reduce:
const keys = key.split(".");
const prop = keys.pop();
keys.reduce((acc, key) => acc[key], state)[prop] = val;
For sure that could also be done with a for loop:
let array = key.split("."), acc = state;
for (var i = 0; i < array.length - 1; i++) {
acc = acc[ array[i] ];
}
acc[ array.pop() ] = val;
For setting a value, you could split the path and reduce the path by walking the given object. If no object exist, create a new property with the name. Later assign the value.
function setValue(object, path, value) {
var keys = path.split('.'),
last = keys.pop();
keys.reduce((o, k) => o[k] = o[k] || {}, object)[last] = value;
}
var test = {};
setValue(test, "first.deep.property", 1);
setValue(test, "and.another.deep.property", 20);
console.log(test);
You could also do this with a single Array.reduce:
const makeObject = (arr, val, obj={}) => {
arr.split('.').reduce((r,c,i,a) => r[c] = i == a.length-1 ? val : {}, obj)
return obj
}
console.log(makeObject("first.deep.property", 1))
console.log(makeObject("and.another.deep.property", 20))

JavaScript ES6 - count duplicates to an Array of objects

I'm creating for my list of products a filter to count all producers and display like this:
Apple (3)
I eliminated the duplicates from array: ["Apple","Apple","Apple"] I used this link:
Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array
But my problem is that I want to count these elements from array and display them in an Array of Objects cause i need to iterate it later.
From this Array of Apples above i need result: [{"Apple": 3},{...},{...}]
I was trying to do this but it returns me object and I can't iterate after it:
How to count duplicate value in an array in javascript
I need an Array of Objects it's not duplicated
I'm using Angular 4.
My code:
component.ts
async ngOnInit() {
this.cart$ = await this.cartService.getCart();
this.subscription = this.productService.getAll().subscribe(products => {
this.category = products.filter(
products => products.category == this.name
);
this.filters();
});
}
filters() {
this.category2 = this.category.map(value => value.producer);
this.filteredArray = this.eliminateDuplicates(this.category2);
console.log(this.filteredArray);
}
eliminateDuplicates(arr) {
let i,
len = arr.length,
out = [],
obj = {};
for (i = 0; i < len; i++) {
obj[arr[i]] = 0;
}
for (i in obj) {
out.push(i);
}
return out;
}
component.html
<div *ngFor="let f of filteredArray">
{{f}}
</div>
You can use reduce to summarize the array and map for form the desired output
let obj = ["Apple", "Apple", "Apple", "Orange"];
let result = Object.values(obj.reduce((c, v) => {
c[v] = c[v] || [v, 0];
c[v][1]++;
return c;
},{})).map(o=>({[o[0]] : o[1]}));
console.log(result);
Here:
const array = ["a", "a", "b"]
const result = { }
for (let i = 0; i < array.length; i++) {
result[array[i]] = (result[array[i]] || 0) + 1
}
Object.keys(result).map(key => ({ [key]: result[key] }))
That last line is the key for
I was trying to do this but it returns me object
you can simply do it by using Lodash countBy function
filters() {
this.category2 = this.category.map(value => value.producer);
this.filteredArray = _.countBy(this.category2);
console.log(this.filteredArray);
// Object {Apple: 3, Orange: 1}
}
You can simply do it by using array.reduce() method
const votes = ['Yes', 'Yes', 'Yes', 'No', 'No', 'Absent'];
const result = votes.reduce((prevValue, vote) => {
if (prevValue[vote]) {
prevValue[vote]++;
} else {
prevValue[vote] = 1;
}
return prevValue;
}, {});
console.log(result);
Output : { Yes: 3, No: 2, Absent: 1 }

create a grouped array using two different arrays

I have below two arrays:
array1 = [{
"type":"test",
"name":"name1"},
{
"type":"dev",
"name":"name2"}]
array2=[{
"type":"test",
"name":"name3"},
{
"type":"dev",
"name":"name4"},
{
"type":"prod",
"name":"name5"}]
I want to group two arrays with "type" and create a new array something like this:
finalArray=[{
"type":"test",
"info":[{
"type":"test",
"name":"name1"}],
[{
"type":"test",
"name":"name3"
}]},
{
"type":"dev",
"info":[{
"type":"dev",
"name":"name2"}],
[{
"type":"dev",
"name":"name4"}]},
{
"type":"prod",
"info":[],
[{
"type":"prod",
"name":"name5"}]
}]
Is there anyway that I can achieve this using javascript, angularjs2, lodash, jquery. I am able to group and create new object as mentioned in using lodash .groupBy. how to add your own keys for grouped output?
But only thing is always I want to push the data from second array in index=1 of "info" and first one to index=0. If any of the array does not have a "type" then the "info" array should have empty/null values.
use _.mapValues to iterate object values with key accessing
var res = _.chain(array1)
.concat(array2)
.groupBy('type')
.mapValues(function(val, key) {
return {
type: key,
info: val
};
})
.values()
.value();
It's possible to achieve the result you want in javascript, or using helper like lodash.
The last part of your question is hard to understand. If an array doesn't have "type", how would you group them. Please provide clearer explanation or modify your expected input and output.
[Updated]
Thanks for your explanation. This is the solution using plain javascript.
// get uniques type from two arrays
const uniqueTypes = new Set(array1
.concat(array2)
.map(x => x.type));
// loop the types, find item in both array
// group it
let result = Array.from(uniqueTypes).reduce((acc, curr) => {
const item1 = array1.find(x => x.type === curr);
const item2 = array2.find(x => x.type === curr);
const info1 = item1 ? [item1] : [];
const info2 = item2 ? [item2] : [];
acc = acc.concat({ type: curr, info: [info1, info2] });
return acc;
}, []);
console.log(result);
jsbin here: https://jsbin.com/mobezogaso/edit?js,console
Here's a working solution :). Hope it helps!
var array1 = [
{
"type":"test",
"name":"name1"
},
{
"type":"dev",
"name":"name2"
}
]
var array2 = [
{
"type":"test",
"name":"name3"
},
{
"type":"dev",
"name":"name4"
},
{
"type":"prod",
"name":"name5"
}
]
var newArray = array1.concat(array2);
var arr1 = [];
var arr2 = [];
var arr3 = [];
var arrTypes = [];
var finalArray = [];
var someArray = [];
for(var i in newArray)
{
if (arrTypes.indexOf(newArray[i].type) === -1){
arrTypes.push(newArray[i].type);
}
if(newArray[i].type === "test"){
arr1.push(newArray[i]);
}
else if(newArray[i].type === "dev"){
arr2.push(newArray[i]);
}
else if(newArray[i].type === "prod"){
arr3.push(newArray[i]);
}
}
someArray.push(arr1);
someArray.push(arr2);
someArray.push(arr3);
for(var j = 0; j < someArray.length; j++){
finalArray.push({
"type": arrTypes[j],
"info": someArray[j]
});
}
console.log(finalArray);
And a short (unreadable?) ES6 solution:
Concat the arrays
Reduce the array into a Map object, with the type as the key
Get the entries iterator - key (type) - value (array of objects)
Use spread to convert the entry iterator to an array
Array#Map the array of entries to the type/info objects
const array1 = [{"type":"test","name":"name1"},{"type":"dev","name":"name2"}];
const array2=[{"type":"test","name":"name3"},{"type":"dev","name":"name4"},{"type":"prod","name":"name5"}];
const result = [...array1.concat(array2).reduce((r, o) => {
r.has(o.type) ? r.get(o.type).push(o) : r.set(o.type, [o]);
return r;
}, new Map).entries()]
.map(([type, info]) => ({
type, info
}));
console.log(result);

How do I return array of duplicate strings in array?

I need a function that takes in an array and will return an array with all the duplicates. I would prefer to use underscore if possible.
given the array:
[
"apple",
"apple",
"pear",
"pear",
"kiwi",
"peach"
]
I need to return an array
[
"apple",
"pear"
]
Many of the methods I've found will return a boolean and not an array of the duplicates.
For example
var fruits = ["apple","apple"];
var uniq_fruits = _.uniq(fruits);
var duplicates_exist = (fruits.length == uniq_fruits.length);
You could use _.countBy to get the word frequencies and then use _.reduce to collect up the values with a frequency greater than one:
function collect_dups(a, n, word) {
if(n > 1)
a.push(word);
return a;
}
var dups = _(words).chain()
.countBy()
.reduce(collect_dups, [])
.value();
Demo: http://jsfiddle.net/ambiguous/gKmfh/1/
Turn your list into a map, then turn the map into a list.
var fruits = ["apple", // ... ];
function fruitCounter(countMap, fruit) {
if (countMap[fruit] == null)
countMap[fruit] = 1;
else
countMap[fruit]++;
return countMap;
}
function dupFinder(dupList, count, fruit) {
if (count > 1)
dupList.push(fruit);
return dupList;
}
var dups = _.reduce(_.reduce(fruits, fruitCounter, {}), dupFinder, []);
It's sort-of unfortunate that there's nothing really like "filter" for the properties of an object, but it's not too bad with "reduce".
edit — a comment from someone better at Underscore than me points out that the inner "reduce" could be replaced by a simpler "countBy":
var dups = _.reduce(_.countBy(fruits, function(f) { return f; }), dupFinder, []);
var common = function(array){
var tally = function(array){
var make_object = {};
_.each(array, function(item){
make_object[item] = (typeof make_object[item] == "undefined") ? 1 : make_object[item] + 1;
});
return make_object;
}(array);
var duplicates = function(obj){
var duplicates = [];
_.each(obj, function(value, key){
if(value > 1){
duplicates.push(key);
}
});
return duplicates;
}(tally);
return duplicates;
};
The idea is very straight forward. Group the items by its value and then find which group having more than 1 items. Finally pick only one item from each group.
lst = [ "apple", "apple", "pear", "pear", "kiwi", "peach"];
var result = _.chain(lst)
.groupBy(function (i) { return i; })
.filter(function (v, k) { return v.length > 1; })
.map(function(v){return v[0]; })
.value();
>>["apple", "pear"]
where arr is your input, you just check to see if the element is a key on the obj object - if it is, pass it to the output array and reloop, otherwise add the key to the object:
function findDupes(arr) {
var obj = {}, newArr = [];
for (var i = 0, l = arr.length; i < l; i++) {
if (obj[arr[i]]) { newArr.push(arr[i]); continue; }
obj[arr[i]] = true;
}
return newArr;
}
var dupes = findDupes(arr);
Giving you have a simple one level array of strings, I would suggest to sort an array first and then loop through it trying to compare current item with the next one.
Something like this:
var fruit = [
"apple",
"apple",
"apple",
"pear",
"pear",
"cantalope"
];
var common = function(array){
var mySortedArray = array.sort();
var myResultArray = [];
for (var i = 0; i < mySortedArray.length - 1; i++)
if ( (mySortedArray[i + 1] == mySortedArray[i]) &&
(mySortedArray[i] != myResultArray[myResultArray.length-1]) )
myResultArray.push(mySortedArray[i]);
return myResultArray;
};
alert(common(fruit));
I started from this function : https://stackoverflow.com/a/840849/1636522
function getDuplicates(arr) {
var i,
len = arr.length,
out = [],
obj = {};
for (i = 0; i < len; i++) {
switch (obj[arr[i]]) {
case undefined: obj[arr[i]] = 1; break;
case 1: obj[arr[i]] = 2; out.push(arr[i]); break;
}
}
return out;
}

Categories