I am wondering what js functions can be used in the following case to get some array values together.
Here I want to concatenate the description values if the date value is null.
var incomes = [ { date: '05/03', description: '1st Description on 05/03', amount: '399.49' },
{ date: null, description: '1st Description continued on 05/03', amount: null },
{ date: null, description: '1st Description continued on 05/03', amount: null },
{ date: '05/03', description: '2nd Description on 05/03', amount: '269.85' },
{ date: null, description: '2nd Description continued on 05/03', amount: null },
{ date: null, description: '2nd Description continued on 05/03', amount: null }];
The result should look like this:
var results = [ { date: '05/03',
description: '1st Description on 05/03, 1st Description continued on 05/03, 1st Description continued on 05/03',
amount: '399.49' },
{ date: '05/03',
description: '2nd Description on 05/03, 2nd Description continued on 05/03, 2nd Description continued on 05/03',
amount: '269.85' }];
I think that we can use the usual loops, conditions, etc. But are there any handy method to solve this?
This really isn't a good use case for reduce/concat types of operations. Reduce is supposed to be given a pure function that only relies on its parameters and doesn't mutate any values. You're trying to produce an array, which would either involve creating the array and then mutating it (adding values), or creating copies of the array (via concat), like this:
const results = incomes.reduce((agg, v) =>
v.date
? agg.concat([v])
: agg.slice(0, -1)
.concat([{
...agg.slice(-1)[0],
description: `${agg.slice(-1)[0].description}, ${v.description}`}]),
[])
As you can see, there's a lot of duplicative sliceing and concating going on here, which is wasteful from a performance perspective. Perhaps more importantly, it's hard to reason with and hard to debug. I'd probably stick with using a for loop that tracks state and pushes to an array instead.
let results = [];
for (let v of incomes) {
if (v.date) {
results.push({...v});
} else {
results[results.length - 1].description += ", " + v.description;
}
}
Related
i have an array of objects that is coming from server.
data:[
{
// values
}
]
below is one object element of that array.
0:
assignedTo:{
name: "Shokat iqbal"
},
category:{
name: "Fan"
},
complainer:{
name: "Testt"
},
details: "Makk Amjum and my name is yeh and i amthose who is ur father"
location: "Room number 87 blockasdas jknaksdnkaj knasdkan kasndka nasdkas"
status: "in-progress"
title: "My fan is damaged"
_id: "5cade948e0b7ce30c8ef2f05"
i want to extract some of its properties like
Assignee: assignedTo.name, category: Category.name, Complainer:complainer.name
and want to make another array of objects which will look like this.
[
{
Assignee: assignedTo.name,
Complainer: complainer.name,
Category: category.name,
title: title,
location: location,
details: details
}
]
please help me how to do this?
Welcome to SO. It's always good to try and show, or talk about some of the solutions that you have tried and where they failed. The community is great but they also appreciate people trying.
Array.map will do the trick for you
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
const formattedData = data.map(record => ({
Assignee: record.assignedTo.name,
Complainer: record.complainer.name,
Category: record.category.name,
title: record.title,
location: record.location,
details: record.details,
}));
Is it possible to use a JavaScript object as a type of mini database? I often find myself needing a kind of database structure when I'm coding in JS but it feels like overkill to use an actual database like MySQL (or similar).
As an example, let's say I need to structure this data as a JS object:
Object idea: Stuff to sell
Items to sell: The junk in the garage
Object structure: List all items including item name, item condition, and item value
In order to make this into a JS object I would maybe write:
var stuffToSell = {};
Then my first item would maybe look like:
var stuffToSell = {
item : "Coffee Maker",
condition : "Good",
price : 5
};
Now to me this seems like I'm on the right track, until I come to add another item and I end up having to use the properties item, condition, and price again in the same JS object — which feels wrong? — or is it?? At this point my brain keeps shouting the word "ARRAY!" at me but I just can't see how I can use an array inside the object, or an object inside an array to achieve what I want.
My end goal (in this simplified example) is to be able to then use object-oriented syntax to be able to access certain items and find out specific information about the item such as price, condition etc. For example if I want to know the price of the "coffee maker" I would like to write something like:
stuffToSell["coffee maker"].price
...and then the result above should be 5.
I feel like I'm on the right track but I think I'm missing the array part? Could someone please tell me what I'm missing or maybe what I'm doing completely wrong! And also if it is wrong to have duplicate property names in the same JS object? For example, is it okay to have:
var stuffToSell = {
item : "Coffee Maker",
price : 5,
item : "Mountain Bike",
price : 10,
item : "26 inch TV",
price : 15
};
...it seems wrong because then how does JS know which price goes with which item??
Thanks in advance :)
You're definitely on the right track!
A lot of people will refer to what you're talking about as a hash.
Here's my suggested structure for you:
var store = {
coffee_maker: {
id: 'coffee_maker',
description: "The last coffee maker you'll ever need!",
price: 5,
},
mountain_bike: {
id: 'mountain_bike',
description: 'The fastest mountain bike around!',
price: 10,
},
tv: {
id: 'tv',
description: 'A big 26 inch TV',
price: 15,
},
}
Having a structure like that will let you do this:
store.mountain_bike.price // gives me 10
Need an array instead, say for filtering or looping over?
Object.keys gives you an Array of all the object's keys in the store ['coffee_maker', 'mountain_bike', 'tv']
// Now we just have an array of objects
// [{id: 'coffee_maker', price: 5}, {id: 'mountain_bike', price: 10} ...etc]
var arr = Object.keys(store).map(el => store[el])
Need to just filter for items that are less than 10?
This will give us an array of products less than 10:
// gives us [{id: 'coffee_maker', price: 5}]
var productsUnder10 = arr.filter(el => el.price < 10)
These techniques can be chained:
var productsOver10 = Object.keys(store)
.map(el => store[el])
.filter(el => el.price > 10)
Need to add a product?
store['new_product'] = {
id: 'new_product',
description: 'The Newest Product',
price: 9000,
}
Here's another way, which would be good to start getting used to.
This is a 'safe' way to update the store, read up on immutability in javascript to learn about it
store = Object.assign({}, store, {
'new_product': {
id: 'new_product',
description: 'The Newest Product',
price: 9000,
}
})
...and another way, that you should also read up on and start using:
This is the object spread operator, basically just an easier way to work with immutable structures
store = {
...store,
'new_product': {
id: 'new_product',
description: 'The Newest Product',
price: 9000,
}
}
Resources
JavaScript Arrow Functions
Object and Array Spread Syntax
Immutable Javascript using ES6 and beyond
You can actually use json or create an array of objects.If using a separate file to store the objects, first load the file. Use array filter method to get an new array which matches the filter condition , like you want to get the item with id 1. This will return an array of objects.
var dict = [{
'id': 1,
'name': 'coffee-mug',
'price': 60
},
{
'id': 2,
'name': 'pen',
'price': 2
}
]
function getItemPrice(itemId) {
var getItem = dict.filter(function(item) {
return item.id === itemId
});
return getItem[0].price;
}
console.log(getItemPrice(1))
JSON objects don't support repeated keys, so you need to set unique keys.
Put an id as your key to group your items:
var stuffToSell = {
'1': {
item: "Coffee Maker",
price: 5
},
'2': {
item: "Mountain Bike",
price: 10
}
.
.
.
}
Now you can access the item's price very fast.
Look at this code snippet (Known Ids)
var stuffToSell = {
'1': {
item: "Coffee Maker",
price: 5
},
'2': {
item: "Mountain Bike",
price: 10
},
'3': {
item: "26 inch TV",
price: 15
}
};
let getPrice = (id) => stuffToSell[id].price;
console.log(getPrice('1'));
See? the access to your items it's fast and your code follows a readable structure.
Look at this code snippet (Item's name as key)
var stuffToSell = {
'Coffee Maker': {
price: 5
},
'Mountain Bike': {
price: 10
},
'26 inch TV': {
price: 15
}
};
let getPrice = (id) => stuffToSell[id].price;
console.log(getPrice('Coffee Maker'));
Look at this code snippet (Item's name: price)
var stuffToSell = {
'Coffee Maker': 5,
'Mountain Bike': 10,
'26 inch TV': 15
};
let getPrice = (id) => stuffToSell[id];
console.log(getPrice('Coffee Maker'));
I'm attempting to list out some messaging threads for my application in the order of the last message (So that newer messages are on the top) and I'm having some problems using the orderBy filter that comes with Angular.
Here's an example of what the object we're sorting looks like.
$scope.messageThreads = {
'102842': {
name: 'John Doe',
avatar: 'http://directlink/img.png',
last_message: 5,
messages: [
{ content: 'Hello!', from: '102842', to: '312124', date: 5 }
]
},
'59251275': {
name: 'Thomas Doe',
avatar: 'http://directlink/img.png',
last_message: 28,
messages: [
{ content: 'Hey jack', from: '59251275', to: '1231251', date: 12 },
{ content: 'Hey Thomas', from: '1231251', to: '59251275', date: 28 }
]
}
}
Stored in a simple object called messageThreads.
In the HTML document, we are looping over these in a Key/Value pair, as so:
<div ng-repeat="(id, thread) in messageThreads | orderBy: '-thread.last_message'">
Thread ID: {{id}} - Last message: {{thread.last_message}}
</div>
Unfortunately, it's not ordering the messages at all. The output displayed is:
Thread ID: 102842 - Last message: 5
Thread ID: 59251275 - Last message: 28
However, it should be:
Thread ID: 59251275 - Last message: 28
Thread ID: 102842 - Last message: 5
Changing -thread.last_message to thread.last_message does not fix the issue.
Here is solution but one problem with that is it converts the items object to an array, you will no longer have access to the key of the “associative array”, as you do with the (key, item) in items snippet
app.filter('orderObjectBy', function() {
return function(items, field, reverse) {
var filtered = [];
angular.forEach(items, function(item,key) {
**item.key = key;** //Here you can push your key to get in returned Object
filtered.push(item);
});
filtered.sort(function (a, b) {
return (a[field] > b[field] ? 1 : -1);
});
if(reverse) filtered.reverse();
return filtered;
};
});
In HTML:
<div ng-repeat="(id, thread) in messageThreads | orderObjectBy:'last_message':true">
Thread ID: {{thread.key}} - Last message: {{thread.last_message}}
</div>
I want to get only the AID from the solution now i am getting. I tried rows[0] but was not successful.
Code:
console.log('The solution is: ', rows);
Output:
The solution is:
[ { AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89 } ]
Use rows[0]["AID"] to access the AID property.
Let's understand your overall data structure here:
var rows = [
{
AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89
}
];
The variable rows is an array of objects. Thus rows[n] gets you a specified object in that array and therefore rows[0] is the first object in the array which would be:
{
AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89
}
So, now you want to access the AID property in that object so you can just do:
rows[0].AID
And, here's a working snippet demo:
var rows = [
{
AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89
}
];
document.write(rows[0].AID);
I have an array and I'm not sure how to access certain keys. What I'm trying to accomplish is simply target certain keys/values in the array. Here's a sample of my array.
var jobs = [
{
// hunting
name: 'Hunting',
available: [
{
name: 'Housemate',
description: 'You stick around the cabin of the hunters. You are the lowest class of the hunters.',
salary: 10
},
{
name: 'Fetcher',
description: 'You are the fetcher of the clan. You gather leather, resources, and skin leather.',
salary: 15
},
{
name: 'Hunter',
description: 'You are a basic hunter of the clan. You hunt for food, meat, and leather.',
salary: 25
},
{
name: 'Elder',
description: 'You are a elder of the clan. You are respected among many, and may ask hunters for arrons.',
salary: 0
}
],
// construction
name: 'Construction',
available: [
{
name: 'Builder',
description: 'You are a builder. You are the lowest class of the construction tier.',
salary: 45
},
{
name: 'Driver',
description: 'You are a driver. You do the fetching and gathering of resources.',
salary: 55
},
{
name: 'Engineer',
description: 'You are a engineer. You do the wiring and electrical work in the construction.',
salary: 65
},
{
name: 'Overseer',
description: 'You are the overseer. You watch over the construction and give orders.',
salary: 80
}
],
}
];
Now keep in mind that I have multiple arrays in one array. Here I try to access the Hunter job category, the Fetcher job, and the construction Engineer salary.
alert(jobs.'Hunting'); // gives 'missing name after . operator' error
alert(jobs.name[0]); // gives 'name is not defined' error
alert(jobs.available.'Fetcher'); //same error as number 1
alert(jobs.available.salary[0]) // gives available is not defined error
How can I access those variables?
Your array of objects is malformed
Your original array contained a single item: one object which had the name and available properties defined twice.
I suspect you want your array to contain two items: two objects, each with a name and available property.
It should be this:
var jobs = [
{
// hunting
name: 'Hunting',
available: [
{
name: 'Housemate',
description: 'You stick around the cabin of the hunters. You are the lowest class of the hunters.',
salary: 10
}, {
name: 'Fetcher',
description: 'You are the fetcher of the clan. You gather leather, resources, and skin leather.',
salary: 15
}, {
name: 'Hunter',
description: 'You are a basic hunter of the clan. You hunt for food, meat, and leather.',
salary: 25
}, {
name: 'Elder',
description: 'You are a elder of the clan. You are respected among many, and may ask hunters for arrons.',
salary: 0
}
]
}, {
// construction
name: 'Construction',
available: [
{
name: 'Builder',
description: 'You are a builder. You are the lowest class of the construction tier.',
salary: 45
}, {
name: 'Driver',
description: 'You are a driver. You do the fetching and gathering of resources.',
salary: 55
}, {
name: 'Engineer',
description: 'You are a engineer. You do the wiring and electrical work in the construction.',
salary: 65
}, {
name: 'Overseer',
description: 'You are the overseer. You watch over the construction and give orders.',
salary: 80
}
],
}
];
Accessing items in the array
alert(jobs[0].name); // Returns 'Hunting'
alert(jobs[0].available[1].name); // Returns 'Fetcher'
alert(jobs[0].available[3].salary); // Returns '0'
Why don't the following examples work?
You can't use a string in dot notation:
alert(jobs.'Hunting');
alert(jobs.available.'Fetcher');
You cannot have a string after the dot. You should have a property name as in object.name, but you first need to define by its index which item in the array you're targeting as in array[i].name.
But even if you changed it to…
alert(jobs[0].Hunting); // OR
alert(jobs[0]['Hunting']);
…it would fail because there is no object with a property name of 'Hunting'.
Square brackets are misplaced:
alert(jobs.name[0]);
alert(jobs.available.salary[0]);
The above examples don't work because you are passing an index inside square brackets after your property name, where they should be placed after the array name. For example:
alert(jobs[0].name);
alert(jobs[0].available[0].salary);
Accessing objects in array by key/value
It looks like you're attempting to access the object's in the array by the value from one of its properties.
For example, above it seems you want to get the object whose property of name has a value of 'Hunting', which cannot be done directly.
You would need to create a function or use a library that provides a function for this, such as Underscore's _.find.
Example of using _.find to get an object by key/value:
var hunting = _.find(jobs, function(obj) {
return obj.name === 'Hunting';
});
View the above examples in JSFiddle
I took the liberty of fixing a syntax error in you example. As you can see in the comments, there were close/opening braces missing between Hunter and Construction.
}]},
// construction
{name: 'Construction',
You will need to use the index notation to get at the different elements in the array.
This will return the Hunter object. From there you can access the individual elements (either name or available).
console.log(jobs[0]);
This will give you the name of the first object's name property.
console.log(jobs[0].name);
This will return the first object under available.
console.log(jobs[0].available[0]);
This will return the name property from the first object under available.
console.log(jobs[0].available[0].name);
Here is a fiddle I created
You didn't build your object correctly, do this :
var jobs = {
// New child object create only for Hunting
hunting: {
// hunting
name: 'Hunting', // optional
available: [
{
name: 'Housemate',
description: 'You stick around the cabin of the hunters. You are the lowest class of the hunters.',
salary: 10
},
{
name: 'Fetcher',
description: 'You are the fetcher of the clan. You gather leather, resources, and skin leather.',
salary: 15
},
{
name: 'Hunter',
description: 'You are a basic hunter of the clan. You hunt for food, meat, and leather.',
salary: 25
},
{
name: 'Elder',
description: 'You are a elder of the clan. You are respected among many, and may ask hunters for arrons.',
salary: 0
}
]
},
// Other section, this time for Construction
construction : {
// construction
name: 'Construction', // Optional too
available: [
{
name: 'Builder',
description: 'You are a builder. You are the lowest class of the construction tier.',
salary: 45
},
{
name: 'Driver',
description: 'You are a driver. You do the fetching and gathering of resources.',
salary: 55
},
{
name: 'Engineer',
description: 'You are a engineer. You do the wiring and electrical work in the construction.',
salary: 65
},
{
name: 'Overseer',
description: 'You are the overseer. You watch over the construction and give orders.',
salary: 80
}
],
}
};
Now you can do :
var construction_jobs = jobs.construction.available;
If you absolutely want keep your array on first dimention you can do it :
var jobs = [
{
// hunting
name: 'Hunting',
available: [ /* objects... */ ]
},
{
// construction
name: 'Construction',
available: [ /* objects... */ ]
}
];
And use lodash lib to get data :
var job = _.findWhere(jobs, {name: 'Hunting'});
To understand, check your console log display on this codepen : http://codepen.io/ArthyFiciel/pen/waGxrm