When to use arrays within JavaScript objects (or mix them)? [closed] - javascript

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Very often I see data structures like this:
var settings = {
languages: [
{
language: 'English',
translation: 'English',
langCode: 'en',
flagCode: 'us'
},
{
...
}
]
};
Or this:
var settings = {
languages: [
{
'en' : {
language: 'English',
translation: 'English',
flagCode: 'us'
}
},
{
...
}
]
};
And this can go many levels deep (within an object there are often other arrays containing further objects)...
Adding arrays brings in another level of complexity when arrays have to be looped through to find a certain object, if we don't know its position in the array. But even if know its position it's still more complicated to use than using purely nested objects, where everything can easily be referred to, using dot notation. Like in this case:
var settings = {
languages: {
'en' : {
language: 'English',
translation: 'English',
flagCode: 'us'
},
'de' : {
...
}
}
};
So when is it a good idea to use arrays within objects and when not?

My simple answer
Use objects ({...}) when you need a collection of key:value pairs
Use arrays ([...]) when you need a collection of objects
Other differences
arrays are ordered, objects are not
arrays are automatically indexed with numbers, objects require you to specify an index
arrays have a .length property, objects do not

There can be multiple reason behind doing this. One of them is,
When you need object in specific order array is helpful here. i.e. in your first example
var settings = {
languages:
{
language: 'English',
translation: 'English',
langCode: 'en',
flagCode: 'us'
},
{
...
}
};
the inner object may shuffle it's position, when it's inside an array it will resides at it's index only.

How would you like your data structure to hold a list of things if not an array?
Lets say you have an object that describes a Person, How would you hold the persons Children?
var kid1 =
{
FirstName: "Abc",
LastName: "Def",
Children: null
};
var kid2 =
{
FirstName: "Abc",
LastName: "Def",
Children: null
};
var dad =
{
FirstName: "Abc",
LastName: "Def",
Children: [kid1,kid2]
};
Children must be an array since a person can have more than one child.

Related

How to change the location of an object key value pair in JavaScript

I've seen similar questions to this one but in different languages and I am struggling to create a JavaScript equivalent.
I am receiving an object and through a function I want to change the location of one (or more) of the properties. For example,
With the original object of
{
individual: [
{
dob: '2017-01-01',
isAuthorized: true,
},
],
business: [
{
taxId: '123',
},
],
product: {
code: '123',
},
}
I would like to change the location of isAuthorized to be in the first object inside of the business array instead of individual.
Like so
{
individual: [
{
dob: '2017-01-01',
},
],
business: [
{
taxId: '123',
isAuthorized: true,
},
],
product: {
code: '123',
},
}
So far I was trying to create an object that would contain the key name and location to change it to, e.g.
{
isAuthorized: obj.business[0]
}
And then loop over the original object as well as the object with the location values and then set the location of that key value pair.
Basically, in this function I want to see that if the original object contains a certain value (in this case isAuthorized) that it will take that key value pair and move it to the desired location.
What you want can easily be achieved by using loadsh, here's a working snippet of how to restructure based on defined structure map. Extended this example to match what you want.
The example is doing a deep clone, if you are fine modifying the original object then skip that step to avoid the overhead.
// input data
const data = {
individual: [
{
dob: '2017-01-01',
isAuthorized: true,
},
],
business: [
{
taxId: '123',
},
],
product: {
code: '123',
},
};
// the structure change map
const keyMap = {
'individual[0].isAuthorized': 'business[0].isAuthorized'
};
function parseData(data,keyMap) {
const newData = _.cloneDeep(data);
for( let [source,dest] of Object.entries(keyMap) ) {
_.set(newData,dest,_.get(newData,source));
_.unset(newData,source);
}
return newData;
}
console.log(parseData(data, keyMap));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
Note: loadsh's set consider any numeric value as an array index so if you are using a numeric object key then use loadash.setWith. I recommend reading examples in doc for a better understanding.
https://lodash.com/docs/4.17.15#set

nested json data minipulation for ngx datatable in angualr -6 / js

I am trying to create a ngx datatable that creates columns dynamically from nested arrays, which with some research is not possible - so to achieve my desired result, I must flatten my nested arrays with the key / values that i need from each nested object into my parent object.
I need to manipulate my data so that my end result is a flat array and contains a line item for each object in the nested array earnings with 'abbreviation' being the key and 'amount' being the value..
I.e
[
{
employee_uuid: 978f37df-7e07-4118-be93-d82507ce5c46,
employee_code: JB00024,
full_name: Thulisile Sandra,
last_name: Bhekiswayo
earnings:[{
abbreviation: "NT HRS"
amount: "45.00"
money: false
name: "Normal Time HRS"
time: true
unique: "7d783469-717e-408a-bc3c-93115cb632dd_true"
uuid: "7d783469-717e-408a-bc3c-93115cb632dd"
value: "45.00"
},
{
abbreviation: "OT HRS"
amount: "25.00"
money: false
name: "Normal Time HRS"
time: true
unique: "7d783469-717e-408a-bc3c-93115cb632dd_true"
uuid: "7d783469-717e-408a-bc3c-93115cb632dd"
value: "45.00"
}],
terminated false
}
...
]
I'd like to look like this:
[
{
employee_uuid: 978f37df-7e07-4118-be93-d82507ce5c46,
employee_code: JB00024,
full_name: Thulisile Sandra,
last_name: Bhekiswayo,
NT HRS: '45.00',
OT HRS, '25.00',
terminated:false
}
...
]
I am not sure how to go about this, I've tried reducing and map functions but no success.. I can add the nested arrays to the parent object with Object.assign but that takes the whole object, I need to create a new parameter from that object..
Any help would be hugely appreciated..
You can use es6 destructuring for this, simply expose whatever properties you need and then "recompose" then into the object shape you want.
For example:
return myEmployeeArray.map(employee => {
const {earn } = employee
earn.map(field => field.abbreviation)
myDesiredObject = { fieldA: employee.abbreviation....fieldE:field.abbreviation}
}
This would get you one of your nested fields

Deep Object Comparison and Property Targeting in JavaScript

I am trying to find out if there any any es6 (or external library) ways to handle deep object comparison and parsing in JavaScript.
Take the following example, where I have a property history, which is an array, embedded within a property services, which is also an array:
{
_id: 4d39fe8b23dac43194a7f571,
name: {
first: "Jane",
last: "Smith"
}
services: [
{
service: "typeOne",
history: [
{ _id: 121,
completed: true,
title: "rookie"
},
{ _id: 122,
completed: false,
title: "novice"
}
]
},
{
service: "typeTwo",
history: [
{ _id: 135,
completed: true,
title: "rookie"
},
{ _id: 136,
completed: false,
title: "novice"
}
]
}
]
}
Now, say a new element is pushed onto the "history" array within the second "services" element, where (service : "typeTwo") -- on the "services" array. I need to identify that's happened, and pull out the entire parent element, because I also need to know what "service" within the "services" array had a new "history" element added.
Is there a way I can scan this entire object and not only determine when something's changed, but actually be able to pull out the section I need reference to? I'm open to either a native JS or JS library option here.
You can check for duplicates like this:
function isEqual(firstObject, secondObject) {
function _equals(firstObject, secondObject) {
let clone = {...{}, ...firstObject}, cloneStr = JSON.stringify(clone);
return cloneStr === JSON.stringify({...clone, ...secondObject});
}
return _equals(firstObject, secondObject) && _equals(secondObject, firstObject);
}
https://jsfiddle.net/b1puL04w/
If you considering libraries has stated, then lodash has _.isEqual which does perform a deep comparison between two values to determine if they are equal.
I have used it extensively for deep comparison in the past.

Is this JavaScript two dimensional array?

const monsters = {
'1': {
name: 'godzilla',
age: 250000000
},
'2': {
Name: 'manticore',
age: 21
}
}
I learn JavaScript from Codecademy, What does this code mean?
Is this two dimensional array? If not, what is it?
The data structure you are showing in your code example is not an array at all, it is an object. Arrays are defined using square brackets ([]) and their keys (indices) are not explicitly declared but rather assigned automatically.
So if you wrote your code like this, for example, you would have an array containing objects:
const monsters = [
{
name: 'godzilla',
age: 250000000
},
{
name: 'manticore',
age: 21
}
]
…so you could access the values by their array index, like so.
monsters[0].name; // godzilla
monsters[1].name; // manticore

Lodash sorting & ordering deep object by values, without losing the key

I'm having a similar need to a previous post on this topic: needing to order and sort an object without losing the keys. However, I have an object of objects:
var o = {
123: { field: "science", name: "zed" },
234: { field: "tech", name: "sara" },
672: { field: "arts", name: "jon" }
}
_.fromPairs(_.sortBy(_.toPairs(o),function(a){ return a[1] }).reverse())
The above uses the lodash solution mentioned the other topic - I'm however not getting any consistency of results (tho am retaining the key!)
Any help would be appreciated.
I’m not clear on what value you intended to sort against above, since objects are incomparable. Let’s say you wanted to sort them by the name field, though — you would find that it still didn’t work.
First some background:
Historically, object properties were considered unordered in ES. The sequence that keys would be enumerated (e.g. by for ... in or Object.keys()) was implementation-specific.
However enumeration order became a specified behavior in ES2015.
That enumeration order codifies what most engines were already doing:
Keys which are integers are enumerated first, from lowest to highest.
String keys are enumerated in the order of assignment.
Symbol keys are enumerated in the order of assignment.
If you need to use integers as ordered keys, you’ll require a different data structure. Map is appropriate:
const o = {
123: { field: "science", name: "zed" },
234: { field: "tech", name: "sara" },
672: { field: "arts", name: "jon" }
}
const { compare } = new Intl.Collator();
const res = new Map(Object
.entries(o)
.sort(([ , a ], [ , b ]) => compare(a.name, b.name))
);
console.log([ ...res ]);
If you need to worry about old IE, an array of key-value entries would also suffice.

Categories

Resources