I'm creating a deck of cards (an array of card objects) by combining an array of suit objects, and an array of card objects, using javascript.
I'm using a forEach loop to loop through the suits, and nested is a map loop for the cards.
The console.log is returning the correct object to push to the new array, however the .push() is only appending a combined object using the last suit and the last card.
Where am I going wrong with this?
I have tried multiple different loops and methods to append to a new array without luck.
Console.log() returns the correct value, but I am unable to push the correct combined objects to a new array.
// Deck of Cards
var suits = [
{ suit: "clubs", color: "black" },
{ suit: "spades", color: "black" },
{ suit: "hearts", color: "red" },
{ suit: "diamonds", color: "red" }
];
var family = [
{ name: "2", value: 2 },
{ name: "3", value: 3 },
{ name: "4", value: 4 },
{ name: "5", value: 5 },
{ name: "6", value: 6 },
{ name: "7", value: 7 },
{ name: "8", value: 8 },
{ name: "9", value: 9 },
{ name: "10", value: 10 },
{ name: "J", value: 10 },
{ name: "Q", value: 10 },
{ name: "K", value: 10 },
{ name: "A", value: 1 },
];
var deck = new Array();
suits.forEach(function (x) {
var arr = family.map((y) => {
var obj = Object.assign(x, y);
console.log(obj);
deck.push(obj);
return obj;
});
console.log(arr);
});
console.log(deck);
try Object.assign({}, x, y) instead of Object.assign(x, y). Currently you're manipulating the object that is x, by adding all properties of y to it.
// Deck of Cards
var suits = [
{suit: "clubs",color: "black"},
{suit: "spades",color: "black"},
{suit: "hearts",color: "red"},
{suit: "diamonds",color: "red"}
];
var family = [
{name: "2",value: 2},
{name: "3",value: 3},
{name: "4",value: 4},
{name: "5",value: 5},
{name: "6",value: 6},
{name: "7",value: 7},
{name: "8",value: 8},
{name: "9",value: 9},
{name: "10",value: 10},
{name: "J",value: 10},
{name: "Q",value: 10},
{name: "K",value: 10},
{name: "A",value: 1},
];
var deck = new Array();
suits.forEach(function(x){
var arr = family.map( (y) => {
var obj = Object.assign({}, x, y);
deck.push(obj);
return obj;
});
});
console.log(deck);
Object.assign(x,y) will put the values of y onto x. You want to leave x alone, so store your properties in a new Object using Object.assign({}, x,y). Consider the demo below:
var suits = [
{suit: "clubs",color: "black"},
{suit: "spades",color: "black"},
{suit: "hearts",color: "red"},
{suit: "diamonds",color: "red"}
];
var family = [
{name: "2",value: 2},
{name: "3",value: 3},
{name: "4",value: 4},
{name: "5",value: 5},
{name: "6",value: 6},
{name: "7",value: 7},
{name: "8",value: 8},
{name: "9",value: 9},
{name: "10",value: 10},
{name: "J",value: 10},
{name: "Q",value: 10},
{name: "K",value: 10},
{name: "A",value: 1},
];
const tmp = suits.reduce((acc, s) => {
return acc.concat(family.map(f => {
return Object.assign({}, f, s);
}));
}, []);
const pre = document.createElement("pre");
pre.innerHTML = JSON.stringify(tmp, null, 4);
document.body.appendChild(pre);
If you can use flatmap, then it can be made significantly simpler:
const suits = [{ suit: "clubs", color: "black" }, { suit: "spades", color: "black" }, { suit: "hearts", color: "red" }, { suit: "diamonds", color: "red" }]
const family = [{ name: "2", value: 2 }, { name: "3", value: 3 }, { name: "4", value: 4 }, { name: "5", value: 5 }, { name: "6", value: 6 }, { name: "7", value: 7 }, { name: "8", value: 8 }, { name: "9", value: 9 }, { name: "10", value: 10 }, { name: "J", value: 10 }, { name: "Q", value: 10 }, { name: "K", value: 10 }, { name: "A", value: 1 }]
const deck = suits.flatMap(s => family.map(f => ({...s, ...f})))
console.log(deck)
A side note, there seems to be a strong convention (presumably from Bridge) of ordering the suits clubs/diamonds/hearts/spades. In English that's easy to remember since they're alphabetic.)
Related
I want to filter the array data that I get from the form.
var form = [
{name: "option_1", value: "A"},
{name: "code_1", value: "36743"}
{name: "option_2", value: "D"},
{name: "code_2", value: "36723"}
{name: "option_3", value: "C"},
{name: "code_3", value: "36543"}
{name: "option_4", value: "B"},
{name: "code_4", value: "36443"}
...
]
I want to filter array by name like this
var option = [ "A", "D", "C", "B"]
var code = [36743, 36723, 36543, 36443]
but I don't how because there is a number in the attribute name
You can filter form array using regular expression then select the desired fields using map function as following:
var form = [
{name: "option_1", value: "A"},
{name: "code_1", value: "36743"},
{name: "option_2", value: "D"},
{name: "code_2", value: "36723"},
{name: "option_3", value: "C"},
{name: "code_3", value: "36543"},
{name: "option_4", value: "B"},
{name: "code_4", value: "36443"}
];
let options = form.filter(a => /option_\d+/.test(a.name)).map(a => a.value);
let codes = form.filter(a => /code_\d+/.test(a.name)).map(a => Number(a.value));
console.log(options, codes);
var form = [
{name: "option_1", value: "A"},
{name: "code_1", value: "36743"},
{name: "option_2", value: "D"},
{name: "code_2", value: "36723"},
{name: "option_3", value: "C"},
{name: "code_3", value: "36543"},
{name: "option_4", value: "B"},
{name: "code_4", value: "36443"}];
/*
var data = form.filter((item) => {
return parseInt(item.value) ? item.value : '';
}) */
var data =form.filter((item) => {
return item.name.includes('code');
}).map(a=>a.value);
console.log(data);
var data1 =form.filter((item) => {
return item.name.includes('option')
}).map(a=>a.value);
console.log(data1);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
I want to store a flat array of object into a nested object form (like tree format).
I found a solution for it but can't find how does variable "root" get all the values.
Can someone help me with this understanding.
var data = [
{id: 10, Name: "a", parentId: null},
{id: 20, Name: "b", parentId: 10},
{id: 30, Name: "c", parentId: 10},
{id: 40, Name: "d", parentId: 20},
{id: 50, Name: "e", parentId: 20},
{id: 60, Name: "f", parentId: 30},
{id: 70, Name: "g", parentId: 30},
{id: 80, Name: "h", parentId: 50},
{id: 90, Name: "i", parentId: 60},
{id: 100, Name: "j", parentId: 70}
];
const idMapping = data.reduce((acc, rec, i) => {
acc[rec.id] = i;
return acc;
},{});
//console.log("idMapping=",idMapping);
let root;
data.forEach(record => {
// Handle the root element
if (record.parentId === null || record.parentId === "") {
root = record;
return;
}
// Use our mapping to locate the parent element in our data array
const parentEl = data[idMapping[record.parentId]];
// Add our current record to its parent's `children` array
parentEl.children = [...(parentEl.children || []), record];
});
console.log("root::",root);
Output is like::
root::
{
id:10,
Name:"a",
parentId:null,
children:(2) [
{
id:20,
Name:"b",
parentId:10,
children:(2) [...]
},
{
id:30,
Name:"c",
parentId:10,
children:(2) [...]
}
]
}
Also, a better solution will also be appreciated. Thanks
I'm trying to transform some data by using Lodash groupBy and map. Here is sample data:
var data = [
{name: 'x', qty: 0, rate: 10},
{name: 'x', qty: 10, rate: 2},
{name: 'y', qty: 5, rate: 20},
{name: 'y', qty: 55, rate: 11}]
I need that data in the format:
var data = [
{name: 'x', pricing: [{qty: 0, rate: 10}, {qty: 10, rate: 2}]},
{name: 'y', pricing: [{qty: 5, rate: 20}, {qty: 55, rate: 11}]}]
The following is my attempt:
var m = _.chain(data)
.groupBy(data, 'name')
.map( function(i) {
return {
name: _.first(i).name,
pricing: _.map(i, function(r) {
return _.pick(r, ['qty', 'rate'])
})
}
})
This produces
[{
"name": "x",
"pricing": [
{"qty": 0, "rate": 10},
{"qty": 10, "rate": 2},
{"qty": 5,"rate": 20},
{"qty": 55,"rate": 11}]
}]
I've been unable to figure out what I'm doing wrong. Maybe this isn't even valid and there is a better way?
You need to map new object and get the picked values.
var data = [{ name: 'x', qty: 0, rate: 10 }, { name: 'x', qty: 10, rate: 2 }, { name: 'y', qty: 5, rate: 20 }, { name: 'y', qty: 55, rate: 11 }],
result = _(data)
.groupBy('name')
.map((pricing, name) => ({
name,
pricing: _.map(pricing, _.partialRight(_.pick, ['qty', 'rate']))
}))
.value();
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
You don't need to use lodash for this - standard Javascript array methods work just fine. Reduce into an object indexed by name, then get that object's values:
var data = [
{name: 'x', qty: 0, rate: 10},
{name: 'x', qty: 10, rate: 2},
{name: 'y', qty: 5, rate: 20},
{name: 'y', qty: 55, rate: 11}]
const obj = data.reduce((a, { name, ...rest }) => {
if (!a[name]) a[name] = { name, pricing: [] };
a[name].pricing.push(rest);
return a;
}, {});
const output = Object.values(obj);
console.log(output);
You can do that using reduce()
var data = [
{name: 'x', qty: 0, rate: 10},
{name: 'x', qty: 10, rate: 2},
{name: 'y', qty: 5, rate: 20},
{name: 'y', qty: 55, rate: 11}]
let res = data.reduce((ac,a) => {
let i = ac.findIndex(x => x.name === a.name);
if(i === -1) i = ac.push({name:a.name,pricing:[]}) - 1
ac[i].pricing.push({qty:a.qty,rate:a.rate});
return ac;
},[])
console.log(res);
Your code is actually fine, except for a small mistake. You start a chain with data, and then you try to groupBy the data. Since non of the items return true for this predicate, all are bundled under a single group, and this is the reason for your single object.
You need to change .groupBy(data, 'name') to .groupBy('name').
Example:
var data = [{ name: 'x', qty: 0, rate: 10 }, { name: 'x', qty: 10, rate: 2 }, { name: 'y', qty: 5, rate: 20 }, { name: 'y', qty: 55, rate: 11 }];
var m = _.chain(data)
.groupBy('name') // group by name, and not by data, 'name'
.map(function(i) {
return {
name: _.first(i).name,
pricing: _.map(i, function(r) {
return _.pick(r, ['qty', 'rate'])
})
}
})
console.log(m);
.as-console-wrapper {
max-height: 100% !important;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
I am having a hard time in finding a way to filter this array by id value, and generate a new one preserving coords with it's filter.
Array example:
var herbs =[
{
"coords":[3300,2796],"items":[
{id: "dandelion",qty: 72},
{id: "sage",qty: 4},
{id: "valerian",qty: 1},
]},
{
"coords":[3300,2800],"items":[
{id: "dandelion",qty: 26},
{id: "valerian",qty: 7},
{id: "sage",qty: 2},
]},
{
"coords":[3300,2804],"items":[
{id: "dandelion",qty: 57},
{id: "sage",qty: 4},
{id: "wormwood",qty: 1},
]}]
I want to filter it by id, generating a new one with it's coords.
Example:
Filtering by id = dandelion
var dandelion =[
{
"coords":[3300,2796],"items":[
{id: "dandelion",qty: 72},
]},
{
"coords":[3300,2800],"items":[
{id: "dandelion",qty: 26},
]},
{
"coords":[3300,2804],"items":[
{id: "dandelion",qty: 57},
]}]
Filtering by id = sage
var sage =[
{
"coords":[3300,2796],"items":[
{id: "sage",qty: 4},
]},
{
"coords":[3300,2800],"items":[
{id: "sage",qty: 2},
]},
{
"coords":[3300,2804],"items":[
{id: "sage",qty: 4},
]}]
Also, this array it's pretty big, I have 467.000 coords. So I plan to filter it and save a new file with each filtered.
You can use reduce for this to push to a new array with items the result of a filter within the reduce call. It only pushes to the new array when the search term is found somewhere in the items:
var herbs =[
{
"coords":[3300,2796],"items":[
{id: "dandelion",qty: 72},
{id: "sage",qty: 4},
{id: "valerian",qty: 1},
]},
{
"coords":[3300,2800],"items":[
{id: "dandelion",qty: 26},
{id: "valerian",qty: 7},
{id: "sage",qty: 2},
]},
{
"coords":[3300,2804],"items":[
{id: "dandelion",qty: 57},
{id: "sage",qty: 4},
{id: "wormwood",qty: 1},
]}]
function filterByID(array, id) {
return array.reduce((a, c) => {
let items = c.items.filter(i => i.id === id )
if (items.length){
a.push({
coords: c.coords,
items: items
})
}
return a
}, [])
}
console.log(filterByID(herbs, "dandelion"))
console.log(filterByID(herbs, "sage"))
It is very straightforward. Use standard Array methods map and filter to get what you want.
var herbs = [{
"coords": [3300, 2796],
"items": [{
id: "dandelion",
qty: 72
},
{
id: "sage",
qty: 4
},
{
id: "valerian",
qty: 1
},
]
},
{
"coords": [3300, 2800],
"items": [{
id: "dandelion",
qty: 26
},
{
id: "valerian",
qty: 7
},
{
id: "sage",
qty: 2
},
]
},
{
"coords": [3300, 2802],
"items": [{
id: "dandelion",
qty: 26
},
{
id: "valerian",
qty: 7
},
//no sage
]
},
{
"coords": [3300, 2804],
"items": [{
id: "dandelion",
qty: 57
},
{
id: "sage",
qty: 4
},
{
id: "wormwood",
qty: 1
},
]
}
];
function filterHerbs(id) {
return herbs.map((h) => {
return {
coords: h.coords,
items: h.items.filter((i) => i.id == id)
}
})//filter result in case of empty item arrays
.filter((h) => h.items.length);
}
var dand = filterHerbs('dandelion')
console.log(dand);
var sage = filterHerbs('sage');
console.log(sage);
const dandelion = herbs.map(
({coords, items}) => items.filter(
({id}) => id === 'dandelion'
).map(ob => ({coords, ...ob})));
How do you append a key called 'Index' with a value being the dictionaries index to the below array? The array should be sorted by Timestamp before this occurs so that TimeStamp:111 comes first and TimeStamp:222 comes second, etc.
For example, see below for original array
items = [
{Id: "01", Name: "A", Price: "1.00", Quantity: "1",TimeStamp:111},
{Id: "02", Name: "B", Price: "10.00", Quantity: "1",TimeStamp:222},
{Id: "04", Name: "C", Price: "9.50", Quantity: "10",TimeStamp:434},
{Id: "03", Name: "a", Price: "9.00", Quantity: "2",TimeStamp:545},
{Id: "06", Name: "b", Price: "100.00", Quantity: "2",TimeStamp:676},
{Id: "05",Name: "c", Price: "1.20", Quantity: "2",TimeStamp:777}
];
The resulting array should look like this:
items = [
{Id: "01", Name: "A", Price: "1.00", Quantity: "1",TimeStamp:111,Index:1},
{Id: "02", Name: "B", Price: "10.00", Quantity: "1",TimeStamp:222,Index:2},
{Id: "04", Name: "C", Price: "9.50", Quantity: "10",TimeStamp:434,Index:3},
{Id: "03", Name: "a", Price: "9.00", Quantity: "2",TimeStamp:545,Index:4},
{Id: "06", Name: "b", Price: "100.00", Quantity: "2",TimeStamp:676,Index:5},
{Id: "05",Name: "c", Price: "1.20", Quantity: "2",TimeStamp:777,Index:6}
];
Here's my attempt: http://jsfiddle.net/chrisguzman/f7dnfrjf/
I've figured out how to append an item to each dictionary, but not how to append its respective iterator.
Also, here it is in angular js (bonus points if there is a way to do it with angular): http://codepen.io/chriscruz/pen/GgjGvO?editors=101
Index started from 0, so you need add +1 for each index, like this
items.forEach(function (d, index) {
d.Index = index + 1;
});
Demo: http://jsfiddle.net/f7dnfrjf/1/
Angular demos:
http://codepen.io/pen/ZYpRag - indexes are displayed as 2, 3, 5, 6
http://codepen.io/pen/zxKapG - indexes are displayed as 1, 2, 3, 4
The runtime system passes 3 parameters to .forEach(): the first is the array element, the second is the index, and the third is the array itself.
Thus:
items.forEach(function (d, i) {
d.Index = i;
});