I have an array of objects with some properties as string values, can someone help me to get array of numbers out it. Here is the array looks like.
scores = [
{
maxScore:"100"
obtainedScore:"79"
passed:"pass"
subject:"Maths"
},
{
maxScore:"100"
obtainedScore:"73"
passed:"pass"
subject:"Science"
},
{
maxScore:"100"
obtainedScore:"82"
passed:"pass"
subject:"English"
}
]
i want obtainedScore and maxScore should be taken out from these objects and place them in two different arrays
i tried this
for (var i =0 ; i < score.length; i++)
{
var marks[i] = parseInt(score[i].obtainedScore) ;
}
and i found NaN.
CORRECT ANSWER BASED ON YOUR ATTEMPT:
var scores = [{
maxScore: "100",
obtainedScore: "79",
passed: "pass",
subject: "Maths"
}, {
maxScore: "100",
obtainedScore: "73",
passed: "pass",
subject: "Science"
}, {
maxScore: "100",
obtainedScore: "82",
passed: "pass",
subject: "English"
}]
var marks = [];
for (var i = 0; i < scores.length; i++) {
marks[i] = parseInt(scores[i].obtainedScore, 10);
}
console.log(marks)
MY SOLN (from before you editted in your attempt)
var scores = [{
maxScore: "100",
obtainedScore: "79",
passed: "pass",
subject: "Maths"
}, {
maxScore: "100",
obtainedScore: "73",
passed: "pass",
subject: "Science"
}, {
maxScore: "100",
obtainedScore: "82",
passed: "pass",
subject: "English"
}]
function decoupler(arr, prop) {
return arr.map(function(item, index) {
return parseInt(item[prop], 10);
});
}
var arr1 = decoupler(scores, "maxScore");
var arr2 = decoupler(scores, "obtainedScore");
console.log(arr1);
console.log(arr2);
Edit: Added radix parameter for parseInt() based on comment by jfriend00.
what about mapping a projection?
var maxScores = scores.map(score => parseInt(score.maxScore, 10))
var obtainedScores = scores.map(score => parseInt(score.obtainedScore, 10))
I am not 100% sure what you want the output to be but :
i want obtainedScore and maxScore should be taken out from these
objects and place them in two different arrays
var arrScore = [],
arrMax = [];
scores.forEach(i => {
arrScore.push(!isNaN(parseInt(i.obtainedScore)) ? parseInt(i.obtainedScore) : 0);
arrMax.push(!isNaN(parseInt(i.maxScore)) ? parseInt(i.maxScore) : 0);
});
Basically this creates two arrays arrScore which will contain each individual score value and arrMax which contains an array of the max scores.
Using the forEach function we iterate the array and push the values into their respective arrays. Note for this we are also ensuring that the type is a valid integer.
scores = [
{
maxScore:"100",
obtainedScore:"79",
passed:"pass",
subject:"Maths"
},
{
maxScore:"100",
obtainedScore:"73",
passed:"pass",
subject:"Science"
},
{
maxScore:"100",
obtainedScore:"82",
passed:"pass",
subject:"English"
}
];
maxScoreArray = new Array();
obtainedScoreArray = new Array();
for (var i = scores.length - 1; i >= 0; i--) {
maxScoreArray.push(Number(scores[i].maxScore));
obtainedScoreArray.push(Number(scores[i].obtainedScore));
}
console.log(maxScoreArray);
console.log(obtainedScoreArray);
Related
I have an array that I'm retrieving from an API. The array looks like this:
[{
"name": "Rachel",
"count": 4,
"fon": "46-104104",
"id": 2
},
{
"name": "Lindsay",
"count": 2,
"fon": "43-053201",
"id": 3
},
{
"name": "Michael",
"count": 5,
"fon": "46-231223",
"id": 4
}]
Then I loop through the array to create an array containing only the names.
function buildName(data) {
for (var i = 0; i < data.length; i++) {
nameList.push(data[i].name)
}
}
This also works so far, but I would like to create an array in which each name occurs as often as the object count says.
For example, the name Michael should appear five times in the array and Lindsay twice.
[
"Rachel",
"Rachel",
"Rachel",
"Rachel",
"Lindsay",
"Lindsay",
"Michael",
"Michael",
"Michael",
"Michael"
"Michael"
]
For each object create a new array using count, and then fill it with the name.
If you use flatMap to iterate over the array of objects. It will return a new array of nested objects but then flatten them into a non-nested structure.
const data=[{name:"Rachel",count:4,fon:"46-104104",id:2},{name:"Lindsay",count:2,fon:"43-053201",id:3},{name:"Michael",count:5,fon:"46-231223",id:4}];
const out = data.flatMap(obj => {
return new Array(obj.count).fill(obj.name)
});
console.log(out);
I've upgraded your functions but you can use the map method
function buildName(data){
for (let i = 0; i < data.length; i++){
let numToLoop = data[i].count
let name = data[i].name
for (let z = 0; z < +numToLoop; z++){
nameList.push(name)
}
}
}
Use an inner while loop inside the for loop:
const data = [{
"name": "Rachel",
"count": 4,
"fon": "46-104104",
"id": 2
},
{
"name": "Lindsay",
"count": 2,
"fon": "43-053201",
"id": 3
},
{
"name": "Michael",
"count": 5,
"fon": "46-231223",
"id": 4
}]
function buildName(data){
const result = [];
for (let i = 0; i < data.length; i += 1) {
let item = data[i];
let count = item.count;
while (count > 0) {
result.push(item.name);
count -= 1;
}
}
return result;
}
console.log(buildName(data));
Just add an inner loop with as many iterations as the "count" property in the object:
function buildName(data) {
const nameList = [];
for (var i = 0; i < data.length; i++) {
for (let j = 0; j < data[i].count; j++) {
nameList.push(data[i].name);
}
}
return nameList;
}
For fun
import { pipe } from 'fp-ts/lib/function';
import { chain, replicate } from 'fp-ts/lib/Array';
const arr = ...
const result = pipe(
arr,
chain(i => replicate(i.count, i.name))
);
You can use .flapMap() for that:
const arr = [{ "name": "Rachel", "count": 4, "fon": "46-104104", "id": 2 }, { "name": "Lindsay", "count": 2, "fon": "43-053201", "id": 3 }, { "name": "Michael", "count": 5, "fon": "46-231223", "id": 4 }];
const result = arr.flatMap(({count, name}) => Array(count).fill(name));
console.log(result);
Effectively you turn every element into an array of the the name property repeated count times which is then flattened into a single array.
It can be done via creating an array with repeated names in this way:
Array(count).fill(name)
Then you have to spread it into resulting array.
You can try this one-liner
const getNames = (data) =>
data.reduce(
(names, { name, count }) => [...names, ...Array(count).fill(name)],
[]
)
Note that a pure function is presented here, which is generally the preferred way of writing code. However, updating your example code might look like this
const getNames = (data) =>
data.reduce(
(names, { name, count }) => [...names, ...Array(count).fill(name)],
[]
)
function buildName(data) {
nameList = getNames(data)
}
I have a json with some characters, and need to print all characters with 3 stars (example)
but how?
json example:
[
{
"name":"Naruto Uzumaki",
"anime":"Naruto",
"star":"2",
"ID":0
},
{
"name":"Son Goku",
"anime":"Dragon Ball",
"star":"3",
"ID":1
},
{
"name":"Monkey D. Luffy",
"anime":"One Piece",
"star":"2",
"ID":2
},
{
"name":"Naruto Uzumaki (Sage Mode)",
"anime":"Naruto",
"star":"3",
"ID":3
}
]
I'm looking for a method to print them all, and be able to randomize between them too
like:
console.log(unit)//{"name":"son Goku"....},{"name":"Naruto"....}
random = 0;
unit = unit[random]
console.log(unit)//{"name":"son Goku"....}
You can use The filter() method to create a new array with your condition from your previous array.
const formatedara = data.filter(x => x.star === "3");
From this new array, you can get any specific object by -
formatedara[index];
const data = [{
name: "Naruto Uzumaki",
anime: "Naruto",
star: "2",
ID: 0,
},
{
name: "Son Goku",
anime: "Dragon Ball",
star: "3",
ID: 1,
},
{
name: "Monkey D. Luffy",
anime: "One Piece",
star: "2",
ID: 2,
},
{
name: "Naruto Uzumaki (Sage Mode)",
anime: "Naruto",
star: "3",
ID: 3,
},
];
const formatData = data.filter((x) => x.star === "3");
console.log(formatData);
You could use the array.map(x => x.star === "3") method. That will create a new array with the items that correspond to your parameters. Also, you're storing the star number as a string, which is not ideal if you want to do maths with it later.
do u want like this ?
unit.forEach((e)=>{
if (e.star == "3") {
console.log(JSON.stringify(e));
//do sth
}
});
var objJson = JSON.parse('[{"name": "Naruto Uzumaki","anime": "Naruto","star": "2", "ID": 0}, { "name": "Son Goku","anime": "Dragon Ball","star": "3","ID": 1 }, {"name": "Monkey D. Luffy", "anime": "One Piece","star": "2","ID": 2},{"name": "Naruto Uzumaki (Sage Mode)","anime": "Naruto","star": "3","ID": 3}]');
var filteredJson = objJson.filter(x => x.star === "3");
console.log(filteredJson);
var random = 0;
filteredJson = filteredJson[random]
console.log(filteredJson);
You could use basic methods also but better is using filter method.
var array = [];
for(i = 0; i < sample.length; i++) {
if (sample[i].star === "3") {
array.push(sample[i]);
}
}
console.log(array)
print all characters with 3 stars (example) but how
for a method to print them all, and be able to randomize between them too like
Just split your problem in multiple steps and it will become clear.
Get characters with 3 stars.
Print characters.
Get a random character from a set of characters.
const characters = [
{
"name":"Naruto Uzumaki",
"anime":"Naruto",
"star":"2",
"ID":0
},
{
"name":"Son Goku",
"anime":"Dragon Ball",
"star":"3",
"ID":1
},
{
"name":"Monkey D. Luffy",
"anime":"One Piece",
"star":"2",
"ID":2
},
{
"name":"Naruto Uzumaki (Sage Mode)",
"anime":"Naruto",
"star":"3",
"ID":3
}
];
// Find all with 3 stars
const threeStarChars = characters.filter(hasTreeStar);
// Print those characters
threeStarChars.forEach(printCharacter);
// Randomize characters
const random3StarCharacter = randomSequenceOf(threeStarChars);
const anyRandomCharacter = randomSequenceOf(characters);
document.querySelector('button:first-child').addEventListener('click', () => printCharacter(random3StarCharacter()));
document.querySelector('button:nth-child(2)').addEventListener('click', () => printCharacter(anyRandomCharacter()));
function hasTreeStar(character) {
return character.star === '3';
}
function printCharacter(character) {
// Some printing logic
console.log(JSON.stringify(character, null, 4));
}
function randomSequenceOf(items) {
const all = [...items];
const current = [...items];
return function () {
if (!current.length) current.push(...items);
return current.splice(randomBetween(0, current.length), 1).pop();
};
}
function randomBetween(min, max) {
return Math.floor(Math.random() * (max - min) + min);
}
<button>Print random 3 star</button>
<button>Print any random</button>
I've got an array of three people. I want to add a new key to multiple objects at once based on an array of indices. Clearly my attempt at using multiple indices doesn't work but I can't seem to find the correct approach.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
}
];
array[0,1].title = "Manager";
array[2].title = "Staff";
console.log(array);
Which returns this:
[
{
"name": "Tom",
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
But I'd like it to return this.
[
{
"name": "Tom",
"title": "Manager"
},
{
"name": "Dick",
"title": "Manager"
},
{
"name": "Harry",
"title": "Staff"
}
]
You cannot use multiple keys by using any separator in arrays.
Wrong: array[x, y]
Correct: array[x] and array[y]
In your case, it will be array[0].title = array[1].title = "manager";
1st method::
array[0].title = "Manager";
array[1].title = "Manager";
array[2].title = "Staff";
array[0,1] will not work.
2nd method::
for(var i=0;i<array.length;i++) {
var msg = "Manager";
if(i===2) {
msg = "Staff"
}
array[i].title = msg
}
You can use a helper function like this
function setMultiple(array, key, indexes, value)
{
for(i in array.length)
{
if(indexes.indexOf(i)>=0){
array[i][key] = value;
}
}
}
And then
setMultiple(array, "title", [0,1], "Manager");
Try this: `
for (var i=0; var<= array.length; i++){
array[i].title = "manager";
}`
Or you can change it around so var is less than or equal to any n range of keys in the index.
EDIT: instead make var <= 1. The point is to make for loops for the range of indices you want to change the title to.
Assuming that you have a bigger set of array objects.
var array = [
{
"name": "Tom",
},
{
"name": "Dick",
},
{
"name": "Harry",
},
.
.
.
];
Create an object for the new keys you want to add like so:
let newKeys = {
'Manager': [0,2],
'Staff': [1]
}
Now you can add more such titles here with the required indexes.
with that, you can do something like:
function addCustomProperty(array, newKeys, newProp) {
for (let key in newKeys) {
array.forEach((el, index) => {
if (key.indexOf(index) > -1) { // if the array corresponding to
el[newProp] = key // the key has the current array object
} // index, then add the key to the
}) // object.
}
return array
}
let someVar = addCustomProperty(array, newKeys, 'title')
How do I push an object into an specified array that only updates that array? My code pushes an object and updates all arrays, not just the specified one.
Here is the structure of the data:
{
"d": {
"results": [
{
"Id": 1,
"cost": "3",
"item": "Project 1",
"fiscalyear": "2014",
"reportmonth": "July"
}
]
}
}
Here is a sample of the desired, wanted results:
{
"Project 1": [
{
"date": "31-Jul-14",
"rating": "3"
},
{
"date": "31-Aug-14",
"rating": "4"
}
],
"Project 2": [
{
"date": "31-Jul-14",
"rating": "2"
}
]
}
This is my attempt:
var results = data.d.results;
var date;
var projectObj = {},
projectValues = {},
project = '';
var cost = '',
costStatus = '';
for (var i = 0, m = results.length; i < m; ++i) {
project = results[i]['item'];
if (!projectObj.hasOwnProperty(project)) {
projectObj[project] = [];
}
// use Moment to get and format date
date = moment(new Date(results[i]['reportmonth'] + ' 1,' + results[i]['fiscalyear'])).endOf('month').format('DD-MMM-YYYY');
// get cost for each unique project
costStatus = results[i]['cost'];
if (costStatus == null || costStatus == 'N/A') {
cost = 'N/A';
}
else {
cost = costStatus;
}
projectValues['rating'] = cost;
projectValues['date'] = date;
projectObj[project].push(projectValues);
}
Here is a Fiddle with the undesired, unwanted results:
https://jsfiddle.net/yh2134jn/4/
What am I doing wrong?
That is because You do not empty it new iteration. Try this:
for (var i = 0, m = results.length; i < m; ++i) {
projectValues = {};
project = results[i]['item'];
....
}
I have an array of objects that I would like to trim down based on a specific key:value pair. I want to create an array that includes only one object per this specific key:value pair. It doesn't necessarily matter which object of the duplicates is copied to the new array.
For example, I want to trim based on the price property of arrayWithDuplicates, creating a new array that only includes one of each value:
var arrayWithDuplicates = [
{"color":"red",
"size": "small",
"custom": {
"inStock": true,
"price": 10
}
},
{"color":"green",
"size": "small",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"blue",
"size": "medium",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"red",
"size": "large",
"custom": {
"inStock": true,
"price": 20
}
}
];
Would become:
var trimmedArray = [
{"color":"red",
"size": "small",
"custom": {
"inStock": true,
"price": 10
}
},
{"color":"green",
"size": "small",
"custom": {
"inStock": true,
"price": 30
}
},
{"color":"red",
"size": "large",
"custom": {
"inStock": true,
"price": 20
}
}
];
Is there a JavaScript or Angular function that would loop through and do this?
EDIT: The property to filter on is nested within another property.
This function removes duplicate values from an array by returning a new one.
function removeDuplicatesBy(keyFn, array) {
var mySet = new Set();
return array.filter(function(x) {
var key = keyFn(x), isNew = !mySet.has(key);
if (isNew) mySet.add(key);
return isNew;
});
}
var values = [{color: "red"}, {color: "blue"}, {color: "red", number: 2}];
var withoutDuplicates = removeDuplicatesBy(x => x.color, values);
console.log(withoutDuplicates); // [{"color": "red"}, {"color": "blue"}]
So you could use it like
var arr = removeDuplicatesBy(x => x.custom.price, yourArrayWithDuplicates);
I don't think there's a built-in function in Angular, but it isn't hard to create one:
function removeDuplicates(originalArray, objKey) {
var trimmedArray = [];
var values = [];
var value;
for(var i = 0; i < originalArray.length; i++) {
value = originalArray[i][objKey];
if(values.indexOf(value) === -1) {
trimmedArray.push(originalArray[i]);
values.push(value);
}
}
return trimmedArray;
}
Usage:
removeDuplicates(arrayWithDuplicates, 'size');
Returns:
[
{
"color": "red",
"size": "small"
},
{
"color": "blue",
"size": "medium"
},
{
"color": "red",
"size": "large"
}
]
And
removeDuplicates(arrayWithDuplicates, 'color');
Returns:
[
{
"color": "red",
"size": "small"
},
{
"color": "green",
"size": "small"
},
{
"color": "blue",
"size": "medium"
}
]
Use Array.filter(), keeping track of values by using an Object as a hash, and filtering out any items whose value is already contained in the hash.
function trim(arr, key) {
var values = {};
return arr.filter(function(item){
var val = item[key];
var exists = values[val];
values[val] = true;
return !exists;
});
}
You can use underscore for this:
//by size:
var uSize = _.uniqBy(arrayWithDuplicates, function(p){ return p.size; });
//by custom.price;
var uPrice = _.uniqBy(arrayWithDuplicates, function(p){ return p.custom.price; });
You can use lodash to remove duplicate objects:
import * as _ from 'lodash';
_.uniqBy(data, 'id');
Here 'id' is your unique identifier
Try the following function:
function trim(items){
const ids = [];
return items.filter(item => ids.includes(item.id) ? false : ids.push(item.id));
}
using lodash you can filter it out easily
the first parameter will be your array and second will be your field with duplicates
_.uniqBy(arrayWithDuplicates, 'color')
it will return an array with unique value
Simple solution although not the most performant:
var unique = [];
duplicates.forEach(function(d) {
var found = false;
unique.forEach(function(u) {
if(u.key == d.key) {
found = true;
}
});
if(!found) {
unique.push(d);
}
});
for (let i = 0; i < arrayWithDuplicates.length; i++) {
for (let j = i + 1; j < arrayWithDuplicates.length; j++) {
if (arrayWithDuplicates[i].name === students[j].name) {
arrayWithDuplicates.splice(i, 1);
}
}
}
this will work perfectly...and this will delete first repeated array.
To delete last repeated array we only have to change
arrayWithDuplicates.splice(i, 1) ; into
arrayWithDuplicates.splice(j, 1);
Off the top of my head there is no one function that will do this for you as you are dealing with an array of objects and also there is no rule for which duplicate would be removed as duplicate.
In your example you remove the one with size: small but if you were to implement this using a loop you'd most likely include the first and exclude the last as you loop through your array.
It may very well be worth taking a look at a library such as lodash and creating a function that uses a combination of it's API methods to get the desired behaviour you want.
Here is a possible solution you could use making use of basic Arrays and a filter expression to check whether a new item would be considered a duplicate before being attached to a return result.
var arrayWithDuplicates = [
{"color":"red", "size": "small"},
{"color":"green", "size": "small"},
{"color":"blue", "size": "medium"},
{"color":"red", "size": "large"}
];
var reduce = function(arr, prop) {
var result = [],
filterVal,
filters,
filterByVal = function(n) {
if (n[prop] === filterVal) return true;
};
for (var i = 0; i < arr.length; i++) {
filterVal = arr[i][prop];
filters = result.filter(filterByVal);
if (filters.length === 0) result.push(arr[i]);
}
return result;
};
console.info(reduce(arrayWithDuplicates, 'color'));
You can check out some literature on Array filtering here
If you need to provide a preference on which item to remove you could define extra parameters and logic that will make extra property checks before adding to a return value.
Hope that helps!
Here is the typescript way
public removeDuplicates(originalArray:any[], prop) {
let newArray = [];
let lookupObject = {};
originalArray.forEach((item, index) => {
lookupObject[originalArray[index][prop]] = originalArray[index];
});
Object.keys(lookupObject).forEach(element => {
newArray.push(lookupObject[element]);
});
return newArray;
}
And
let output = this.removeDuplicates(yourArray,'color');
This is just another 'feature' based on yvesmancera's solution (after I started tinkering for my own solution) Also noted we are only allowed to currently use IE 11, so limited ES5 is allowed.
var newArray = RemoveDuplicates(myArray,'Role', 2);
function RemoveDuplicates(array, objKey, rtnType) {
var list = [], values = [], value;
for (var i = 0; i < array.length; i++) {
value = array[i][objKey];
if(values.indexOf(value) === -1){
list.push(array[i]);
values.push(value);
}
}
if(rtnType == 1)
return list;
return values;
};
Hoping this will work for most, if not all arrays when filtering out objects based on a single object property value.