Related
I am trying to understand the logic of using array methods within Map functions (such as push, slice, etc). Below, I have a function that is trying to add an element in the middle of a 2D array, but it comes out completely blank. Not sure what I am missing
function array () {
let numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// Attempted outcome = [[1, 2, "Hello", 3], [4, 5, "Hello", 6], [7, 8, "Hello", 9]]
let newNumbers = numbers.map(function (row) {
return [row.slice(2, 0, "Hello")]
})
Logger.log(newNumbers);
}
In your script, how about the following modification?
From:
let newNumbers = numbers.map(function (row) {
return [row.slice(2, 0, "Hello")]
})
To:
let newNumbers = numbers.map(function (row) {
row.splice(2, 0, "Hello");
return row;
});
or, in this case, the following modification might be able to be used.
let newNumbers = numbers.map(([a, b, ...c]) => [a, b, "Hello", ...c]);
Testing:
let numbers = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// Attempted outcome = [[1, 2, "Hello", 3], [4, 5, "Hello", 6], [7, 8, "Hello", 9]]
let newNumbers = numbers.map(function (row) {
row.splice(2, 0, "Hello");
return row;
});
console.log(newNumbers);
Reference:
splice()
Beginner programmer here, apologies in advance if my vocabulary is not really accurate while explaining my issue.
I have a script that creates a custom menu (view) and hides different set of columns based on the view you want to see.
How can I change the script so instead of typing all my columns I can get an array of columns (in this case array [1 to 4] and [7 to 13])?
Below the particular section of my code that I'd like to change
function hideColumnsAll30() {
const obj = [{ sheetName: "Planning / Tracking", hide: [1, 2, 3, 4, 7, 8, 9, 11, 12, 13 ] }, { sheetName: "Resources", hide: [2, 4, 5, 9]}, {sheetName: "Documentation", hide:[2, 4, 5, 9]} ];
sample_(obj);
}
And here is the full script if it helps solving my issue
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Custom View')
.addItem('All - 30 days', 'hideColumnsAll30')
.addItem('All - 1 year', 'hideColumnsAll1y')
.addItem('Unhide All', 'showColumns')
.addToUi();
function showColumns() {
const sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
showColumnsInAllSheets_(sheets);
}
function hideColumnsAll30() {
const obj = [{ sheetName: "Planning / Tracking", hide: [1, 2, 3, 4, 7, 8, 9, 11, 12, 13 ] }, { sheetName: "Resources", hide: [2, 4, 5, 9]}, {sheetName: "Documentation", hide:[2, 4, 5, 9]} ];
sample_(obj);
}
function hideColumnsAll1y() {
const obj = [{ sheetName: "Planning / Tracking", hide: [1, 3, 4, 5, 6, 7, 8, 9, 11, 12, ] }, { sheetName: "Resources", hide: [2, 4, 5, 9]}, {sheetName: "Documentation", hide:[2, 4, 5, 9]} ];
sample_(obj);
}
Thanks in advance for your help!
From your following replying,
I need to type all the columns manually -> [1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13] I would like to have 2 arrays, like this -> [1 - 4], [7 -13]
I guessed that you wanted to retrieve an array of [1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13] by using 2 arrays like [1 - 4], [7 -13]. If my understanding is correct, how about the following sample script?
Sample script:
const input = [[1, 4], [7, 13]]; // 1st and 2nd element of each array are start and end values, respectively.
const res = input.flatMap(([start, end]) => [...Array(end)].map((_, i) => i + 1).slice(start - 1, end));
console.log(res);
When this script is run, an array of [ 1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13 ] is obtained.
References:
map()
flatMap()
Added:
From your following reply,
I actually found similar piece of code to add to my script online. However it does not fit my case as I need to give the name of each sheets where I want to hide columns.
And, in your provided script, I found the following message.
I have other speadsheets with 1000+ columns, so I cannot hide them manually from 1 to 1000. This is the reasons why I'm trying to include several arrays in my script
In this case, is the following script your expected script?
const columns = input => input.flatMap(([start, end]) => [...Array(end)].map((_, i) => i + 1).slice(start - 1, end));
function hideColumnsAll30() {
const obj = [{ sheetName: "Planning / Tracking", hide: columns([[1, 4], [7, 13]]) }, { sheetName: "Resources", hide: [2, 4, 5, 9]}, {sheetName: "Documentation", hide:[2, 4, 5, 9]} ];
sample_(obj);
}
At hide: columns([[1, 4], [7, 13]]), hide: [ 1, 2, 3, 4, 7, 8, 9, 10, 11, 12, 13 ] is created.
Suggestion
In your script I am not sure where you will use the arrays 1-4 and 7-13 since in the scripts specially on the part { sheetName: "Planning / Tracking", hide: [1, 2, 3, 4, 7, 8, 9, 11, 12, 13 ] } you are skipping number 10 here and on the other function you skipped 2.
Here's a suggestion on how you can use an array to your function. You can just add a new variable outside the functions to make it global variables, here is where you will insert the array values you want. You can then access these variables in any of your functions so you only have to edit one line in case you will adjust the columns.
Try this code:
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Custom View')
.addItem('All - 30 days', 'hideColumnsAll30')
.addItem('All - 1 year', 'hideColumnsAll1y')
.addItem('Unhide All', 'showColumns')
.addToUi();
};
//Declare arrays here***
//Put in array the columns for Resources and Documentation sheets
var resDocArray = [2,4,5,9];
//Put in array the columns for the planning/tracking tab for 2 different functions
var colAll30d = [1, 2, 3, 4, 7, 8, 9, 11, 12, 13];
var colAll1y = [1, 3, 4, 5, 6, 7, 8, 9, 11, 12]
//***
function showColumns() {
const sheets = SpreadsheetApp.getActiveSpreadsheet().getSheets();
showColumnsInAllSheets_(sheets);
};
function hideColumnsAll30() {
const obj = [{ sheetName: "Planning / Tracking", hide: colAll30d }, { sheetName: "Resources", hide: resDocArray}, {sheetName: "Documentation", hide:resDocArray} ];
sample_(obj);
};
function hideColumnsAll1y() {
const obj = [{ sheetName: "Planning / Tracking", hide: colAll1y }, { sheetName: "Resources", hide: resDocArray}, {sheetName: "Documentation", hide:resDocArray} ];
sample_(obj);
};
function sample_(obj) {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheets = ss.getSheets();
showColumnsInAllSheets_(sheets);
const sheetObj = sheets.reduce((o, s) => (o[s.getSheetName()] = s, o), {});
obj.forEach(({ sheetName, hide }) => {
if (sheetObj[sheetName]) {
hide.forEach(h => sheetObj[sheetName].hideColumns(h, 1));
}
});
};
function showColumnsInAllSheets_(sheets) {
sheets.forEach(s => s.showColumns(1, s.getMaxColumns()));
};
You can also add the arrays the way Tanaike suggested.
Let me know if this helps!
Reference:
Hide columns in multiple sheets
i have this service that give back this Json result :
{
"MANNOUBA": 1,
"Medinine": 4,
"Gabes": 5,
"Tunis": 22,
"Beja": 3,
"Kebili": 0,
"Sfax": 11,
"Laundry Making": 6,
"italia": 0,
"Sousse": 6,
"Desk": 1,
"Jendouba": 3,
"Mahdia": 6,
"Ben Arous": 19,
"Zaghouan": 4,
"Gafsa": 0,
"Kairouan": 6,
"Monastir": 18,
"metos": 1,
"Eleonetech": 2,
"Nabeul": 22,
"Mannouba": 9,
"BENAROUS": 8,
"Ariana": 21,
"Bizerte": 3
}
i want to put this data in a Barchart For my angular Project with the names in the X axis and the Numbers in the Y axis
With using Highcharts, you can preprocess your data to the: [name, y] format and use category axis type. Example:
for (let key in data) {
chartData.push([key, data[key]]);
}
Highcharts.chart('container', {
xAxis: {
type: 'category'
},
series: [{
type: 'column',
data: chartData
}]
});
Live demo: http://jsfiddle.net/BlackLabel/cjk3uboh/
Highcharts angular wrapper: https://www.npmjs.com/package/highcharts-angular
I have a function to denormalize json data.
Json data looks like:
-entries
- entry
- skus
What I am trying to do is to create an array of objects where entries with more than 1 SKUs should be repeated the x times, where x is the number of skus (length of the sku array); each time switching the data of the skus.
The problem is that the sku data does not switch, and the same skus are shown multiple times in the resulting array.
When I debug step by step, the array is appended fine at the beginning, however when function proceeds the correctly appended elements of the array are overwritten.
Here the function code:
let data = [
{
name: 'a',
skus: [1, 2],
},
{
name: 'b',
skus: [3, 4],
},
{ name: 'c', skus: [5] },
{ name: 'd', skus: [6, 7, 8] },
];
function flatten(data) {
let newArray = [];
for (i in data) {
const el = {};
el.name = data[i].name;
let skus = data[i].skus;
for (j in skus) {
el.sku = skus[j];
newArray.push(el);
console.log(el);
}
}
return newArray;
}
what I am trying to achieve is to return a new array which is so:
[
{ name: a,
sku: 1
},
{ name: a,
sku: 2
},
{
name: b,
sku: 3,
},
{
name: b,
sku: 4,
}... and so on ]
Thanks
You want to achieve the following conversion.
From
const data = [
{name: 'a', skus: [1, 2]},
{name: 'b', skus: [3, 4]},
{name: 'c', skus: [5]},
{name: 'd', skus: [6, 7, 8]},
];
To
[
{"name": "a", "sku": 1},
{"name": "a", "sku": 2},
{"name": "b", "sku": 3},
{"name": "b", "sku": 4},
,
,
,
]
Modification points:
I think that the reason of your issue is due to the call by reference. When the object el is put to the array with newArray.push(el), el is changed by the next loop. By this, I think that your issue occurs. In this case, it is required to copy the object and put to the array.
When above points are reflected to your script, it becomes as follows.
Modified script:
From:
newArray.push(el);
To:
newArray.push(Object.assign({}, el));
Testing:
let data = [
{name: 'a', skus: [1, 2]},
{name: 'b', skus: [3, 4]},
{name: 'c', skus: [5]},
{name: 'd', skus: [6, 7, 8]},
];
function flatten(data) {
let newArray = [];
for (i in data) {
const el = {};
el.name = data[i].name;
let skus = data[i].skus;
for (j in skus) {
el.sku = skus[j];
newArray.push(Object.assign({}, el));
// console.log(el);
}
}
return newArray;
}
console.log(flatten(data))
Other pattern:
In your case, the following script can be also used.
const data = [
{name: 'a', skus: [1, 2]},
{name: 'b', skus: [3, 4]},
{name: 'c', skus: [5]},
{name: 'd', skus: [6, 7, 8]},
];
const res = data.reduce((ar, {name, skus}) => {
skus.forEach(e => ar.push({name: name, sku: e}));
return ar;
}, []);
console.log(res);
Reference:
Object.assign()
UPDATE(2):
I got it to work so here is the working fiddle. See below for my solution. If you know of any other solutions, let me know. Thanks! otherwise...feel free to use this example :)
UPDATE(1):
I've continued working on it and here is my updated fiddle. I think I'm overriding my variable/data values each time I loop through. Any help is greatly appreciated.
ORIGINAL POST:
I have a jsfiddle here that shows what I'm trying to do.
I have a series of data in json format that has multiple objects(i.e.,
[
{"name":"name1", "data":[[0,4.3],[1,2.47],[2,0.2],etc.]},
{"name":"name2", "data":[[0,4.3],[1,2.47],[2,0.2],etc.]}
]
)
and am graphing with HighCharts line graphs. Instead, I'd like to define the series data to objects from multiple subtasks all on the same graph. (the variable is better shown in the jsfiddle link)
[
{"subtask":"id1", "":[
{"name":"name1", "data":[[0,4.3],[1,2.47],[2,0.2],etc.]},
{"name":"name2", "data":[[0,3.5],[1,2.12],[2,0.1],etc.]}
]
},
{"subtask":"id2", "":[
{"name":"name1", "data":[[0,4.1],[1,2.23],[2,0.4],etc.]},
{"name":"name2", "data":[[0,3],[1,2.62],[2,0.15],etc.]}
]
}
]
and I'd like the graph to draw a line for each name/data for each subtask (i.e., the graph draw a line for id1.name1.data, id1.name2.data, id2.name1.data, and id2.name2.data)
My Solution:
I got it to work so here is the working fiddle. If you know of any other solutions, let me know. Thanks! otherwise...feel free to use this example :)
// what currently works
var jsonFormatThatWorks = [{
"name": "name1",
"data": [
[0, 100],
[10, 70.02],
[20, 60.7],
[30, 45.3],
[40, 35],
[50, 32],
[60, 14],
[70, 0]
]
},
{
"name": "name2",
"data": [
[0, 100],
[10, 30],
[20, 13],
[30, 8],
[40, 7.5],
[50, 5.2],
[60, 4.54],
[70, 0.3],
[80, 0.01]
]
}
]
// format I want/need to be able to access/graph
var jsonFormatIWant = [{
"p1": "12345",
"taskName": "z-echo",
"taskData": [{
"subTaskId": "z8-echo",
"someTaskStatus": "Rejected",
"someTaskData": [{
"objectId": "name1",
"objectData": [
[0, 100],
[10, 90.80],
[20, 80.37],
[30, 75],
[40, 66],
[50, 33],
[60, 15],
[70, 0]
]
},
{
"objectId": "name2",
"objectData": [
[0, 100],
[10, 23],
[20, 15],
[30, 11],
[40, 8.5],
[50, 6.2],
[60, 3.44],
[70, 0.7],
[80, 0.5]
]
}
]
},
{
"subTaskId": "z9-echo",
"someTaskStatus": "Accepted",
"someTaskData": [{
"objectId": "name1",
"objectData": [
[0, 100],
[10, 70.02],
[20, 60.7],
[30, 45.3],
[40, 35],
[50, 32],
[60, 14],
[70, 0]
]
},
{
"objectId": "name2",
"objectData": [
[0, 100],
[10, 30],
[20, 13],
[30, 8],
[40, 7.5],
[50, 5.2],
[60, 4.54],
[70, 0.3],
[80, 0.01]
]
}
]
}
]
}]
// my chart
$(document).ready(function() {
var options = {
chart: {
renderTo: 'container',
type: 'line',
zoomType: 'xy',
panning: true,
panKey: 'shift'
},
xAxis: {
title: {
text: 'Some X Label'
},
crosshair: true
},
plotOptions: {
series: {
marker: {
radius: 1
},
allowPointSelect: true
}
},
yAxis: {
labels: {
format: '{value} %'
},
floor: 0,
ceiling: 100,
title: {
text: 'Value (%)'
},
crosshair: true,
gridLineDashStyle: 'ShortDash',
gridLineColor: '#aaaaaa'
},
title: {
text: 'Sample Chart'
},
subtitle: {
text: 'Click and drag to zoom in. Hold down shift key to pan.'
},
legend: {
layout: 'vertical',
align: 'right',
verticalAlign: 'middle',
borderWidth: 0
},
series: seriesOptions
};
var chart = new Highcharts.Chart(options);
});
var seriesOptions = [],
seriesCounter = 0
var data = jsonFormatIWant[0]
var taskData = data.taskData
taskData.forEach(function(element, i) {
element.someTaskData.forEach(function(childElement, j) {
seriesOptions[seriesCounter] = {
//task: element.subTaskId,
name: element.subTaskId + "_" + element.someTaskData[j].objectId,
data: element.someTaskData[j].objectData
}
seriesCounter += 1
//console.log(seriesCounter)
childElement.objectData.forEach(function(grandChildElement, h) {})
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/series-label.js"></script>
<script src="https://code.highcharts.com/modules/exporting.js"></script>
<div id="container"></div>
<!-- I'd like to be able to graph each objects data for each subTask
(i.e., z8-echo and z9-echo from the data jsonFormatIWant variable beneath the chart definition)
something like: taskData[0].someTaskData and taskData[1].someTaskData -->