turn a flat array into cell like objects for a grid - javascript

I have an array that looks like similar to this,
[
['column1', 'column2', 'column3', 'column4', 'column5'],
['2column1', '2column2', '2column3', '2column4', '2column5']
]
I wanting to turn this array into table that looks similar to this,
header1
header2
header3
header4
header5
column1
column2
column3
column4
column5
2column1
2column2
2column3
2column4
2column5
I want to turn array above into an array of objects if possible that would look like this,
[
[
{ col:a, row: 1, cell_value: 'column1'},
{ col:b, row: 1, cell_value: 'column2'},
{ col:c, row: 1, cell_value: 'column3'},
{ col:d, row: 1, cell_value: 'column4'},
{ col:e, row: 1, cell_value: 'column5'}
],
[
{ col:a, row: 2, cell_value: '2column1'},
{ col:b, row: 2, cell_value: '2column2'},
{ col:c, row: 2, cell_value: '2column3'},
{ col:d, row: 2, cell_value: '2column4'},
{ col:e, row: 2, cell_value: '2column5'}
]
]
I have a function to create the column letters,
export const columnToLetter = (column) => {
let temp, letter = '';
while (column > 0) {
temp = (column - 1) % 26;
letter = String.fromCharCode(temp + 65) + letter;
column = (column - temp - 1) / 26;
}
return letter;
}
and this is my attempt to create the above array objects,
const data = payload.formatted_values.map((value, index) => {
let columnCount = 0;
while (columnCount <= payload.formatted_values.length) {
const singleCell = {
col: columnToLetter(index+1),
row: columnCount+1,
cell_value: value[columnCount]
}
columnCount++;
return singleCell;
}
});
But the output I get is incorrect, I get this structure,
{col: 'A', row: 1, cell_value: 'Fav'}
{col: 'B', row: 1, cell_value: 'red'}
{col: 'C', row: 1, cell_value: ''}
Which is not what I want, can any advise how I would turn the flat array I start with into a object with the attributes I want?

You could map a nested result.
const
data = [['column1', 'column2', 'column3', 'column4', 'column5'], ['2column1', '2column2', '2column3', '2column4', '2column5']],
result = data.map((a, row) => a.map((cell_value, col) => ({
col: (col + 10).toString(36).toUpperCase(),
row: row + 1,
cell_value
})));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You could just loop over it like so:
function makeColumn(arr)
{
var outArr = []
var rowCounter = 0
var cCounter = 97
arr.forEach((item,index) => {
outArr.push([])
item.forEach((i2,ind2) => {
outArr[index].push({
col:String.fromCharCode(cCounter++),
row: rowCounter,
cell_value: arr[rowCounter][ind2]
})
})
rowCounter++
cCounter = 97
})
return outArr
}

Using for and map()
const data = [
['column1', 'column2', 'column3', 'column4', 'column5'],
['2column1', '2column2', '2column3', '2column4', '2column5']
]
const res = []
for (let i = 0; i < data.length; i++) {
res.push(data[i].map((item, index) => {
return { col: String.fromCharCode(index+97), row: i+1, cell_value: item }
}))
}
console.log(res)

You can simply achieve this by just using Array.map() method.
Live Demo :
const arr = [
['column1', 'column2', 'column3', 'column4', 'column5'],
['2column1', '2column2', '2column3', '2column4', '2column5']
];
const res = arr.map((elem, index) => {
return elem.map((col, i) => {
return {
col: String.fromCharCode(97 + i),
row: index + 1,
cell_value: col
}
})
});
console.log(res);

Related

dynamically get columns from 2D array

I have a 2D array of row,through which i want get the column coordinates/information just like i got for the row(rowArr2D)
So,in my Column(colArr2D) i'm just getting all 4th position values in the array since i passed have oRowCount in the function
my goal is to get all columns respectively.
Example:
Row:[ [ 0, 1, 2, 3, 4, 5, 6 ], [ 0, 1, 2, 3, 4, 5, 6 ], [ 0, 1, 2, 3, 4, 5, 6 ], [ 0, 1, 2, 3, 4, 5, 6 ] ]
Columns: [[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3],[0,1,2,3]]
mockTable = { // mocking the portions of my code
GetRowsCount : () => 4,
GetRow: (x) => ({
GetCellsCount : () => 7,
GetCell : (x) => x
})
}
CTable_prototype_GetTableMapping = function(currentTable)
{
//get row information
let oRowCount = currentTable.GetRowsCount();
const rowArr2D = Array(oRowCount);
for (let i = 0; i < oRowCount; i++) {
//get cell information and cell count
let oRow = currentTable.GetRow(i);
let oCellCount = oRow.GetCellsCount();
rowArr2D[i] = Array(oCellCount);
for (let j = 0; j < oCellCount; j++) {
//get cell content
let oCell = oRow.GetCell(j);
rowArr2D[i][j] = oCell;
}
}
// get column information
const colArr2D = (array, colCount) => {
const result = [];
array.forEach(e => {
result.push(e[colCount]);
});
console.log(result);
return result;
};
colArr2D(rowArr2D, oRowCount);
return rowArr2D
console.log(rowArr2D);
};
const theArray = CTable_prototype_GetTableMapping(mockTable);
console.log("full 2D array", theArray)
Give this a try
const colArr2D = (array) =>
array[0].map((a, i) =>
array.map(b => b[i])
);
const arr = [[1,2,3],[4,5,6],[7,8,9]];
console.log(colArr2D(arr))

How to write a proper constructor function extending the Array class

Scenario
I have the following piece of code:
const composeMatrix = (nRow, nCol, filler) => Array(nRow).fill(Array(nCol).fill(filler));
class Matrix extends Array {
constructor({ nRows = 3, nCols = 3, filler = 0 } = {}) {
super(...composeMatrix(nRows, nCols, filler));
}
makeTranspose() {
const mat = this;
const column = mat[0];
return column.map((_, i) => {
return mat.map((row) => row[i]);
});
}
}
I'm instantiating a new Matrix like this:
const mat = new Matrix({ nRows: 4, filler: 1 });
Logging mat to the console gives me as expected,
Matrix(4) [
[ 1, 1, 1 ],
[ 1, 1, 1 ],
[ 1, 1, 1 ],
[ 1, 1, 1 ]
]
Problem
Now when I call the makeTranspose method of the class, it returns me this:
[
Matrix(4) [ 1, 1, 1, 1 ],
Matrix(4) [ 1, 1, 1, 1 ],
Matrix(4) [ 1, 1, 1, 1 ]
]
Expected output:
Matrix(3) [
[ 1, 1, 1, 1 ],
[ 1, 1, 1, 1 ],
[ 1, 1, 1, 1 ]
]
What I figured is, the map function calls the constructor of this subclass every time while iterating through the array, which in turn calls super, which then calls the composeMatrix function and a new Matrix gets made.
How can I fix this?
I want a class to extend Array with some added methods.
The constructor needs to take some relevant parameters and function as expected.
I don't want to add functions to the prototype.
A matrix is not an array. You're better off using composition over inheritance.
Array.create = (length, mapping) =>
Array.from({ length }, (value, index) => mapping(index));
class Matrix {
constructor(rows, cols, data) {
this.rows = rows;
this.cols = cols;
this.data = data;
}
static create(rows, cols, mapping) {
const data = Array.create(rows, row =>
Array.create(cols, col => mapping(row, col)));
return new Matrix(rows, cols, data);
}
transpose() {
const { rows, cols, data } = this;
return Matrix.create(cols, rows, (row, col) => data[col][row]);
}
}
const mat = Matrix.create(4, 3, (row, col) => 1);
console.log(mat.transpose());
Using a functional style of programming.
const array = (length, mapping) =>
Array.from({ length }, (value, index) => mapping(index));
const Matrix = (rows, cols, data) => ({ rows, cols, data });
const matrix = (rows, cols, mapping) =>
Matrix(rows, cols, array(rows, row =>
array(cols, col => mapping(row, col))));
const transpose = ({ rows, cols, data }) =>
matrix(cols, rows, (row, col) => data[col][row]);
const mat = matrix(4, 3, (row, col) => 1);
console.log(transpose(mat));

Converting relationships between data inside a JavaScript Array

I have got a function that produces an array that is made up of X amount of sub-arrays containing Y amount of objects. Both of these factors are passed to a function to produce an array that looks something like this:
[
[ { '0': 3 }, { '1': 4 }, { '2': 6 }, 'Estimate:': '0jvyt8a' ],
[ { '0': 4 }, { '1': 6 }, { '2': 3 }, 'Estimate:': 'mc973fs' ],
[ { '0': 4 }, { '1': 1 }, { '2': 3 }, 'Estimate:': 'vwsfh8k' ],
[ { '0': 4 }, { '1': 3 }, { '2': 5 }, 'Estimate:': 'n6xzge3' ],
[ { '0': 8 }, { '1': 7 }, { '2': 1 }, 'Estimate:': 'v0jn7bh' ]
]
My question is, is there a way I can convert this array from this structure. To a structure shown below:
[
[1,{1: "vwsfh8k"}, {2: "v0jn7bh"}]
[3,{1: "0jvyt8a"}, {2: "mc973fs"}, {3:"vwsfh8k"}, {4:"n6xzge3"}]
]
Basically, my aim is to take the original array generated by the script (see below) and pass it through another function to record how many times each number was present and what it's 'estimate' number was.
In this example, I just created random numbers between 0 and 10 so an option would be to iterate and count each value I guess but unfortunately, I can't do this because eventually I will be using 5-letter combinations instead of numbers but numbers were easiest to show for an example and proof of concept.
So, I guess, I need to get an array of each unique value and then look at each value up in the original array to find out what estimate IDs have it present. Unfortunately, I don't have even an idea of where, to begin with, this, so I was hoping you guys can help.
Code to generate random array:
// Making an empty array
const arr = [];
//Generating the estimate IDs and placing them all in their own object in their own array.
function estimateGen(length, nodes) {
for (var i = 0; i < length; i++) {
const estimate = [];
let estimateVal = Math.random().toString(36).replace('0.','').slice(0,7);
estimate[`Estimate:`] = estimateVal;
arr.push(estimate);
nodeGen(estimate, nodes)
}
}
// Adding x amount of nodes between 1 and 10 into each estimate sub-array in their own objects.
function nodeGen(estimate, nodes) {
for (var i = 0; i < nodes; i++) {
const node = {};
let nodeID = Math.floor(Math.random() * 10) + 1;
node[i] = nodeID;
estimate.push(node);
}
}
// Calling the function and saying how many nodes per estimate we want.
estimateGen(5, 3);
console.log(arr);
If you have any suggestions on how to improve this code or as to why the estimate values in the sub-array are always last in the array that would be very helpful.
Thank you
--- EDIT ---
I have changed the code that generates the original array to produce a simpler array.
// Making an empty array
const arr = [];
//Generating the estimate IDs and placing them all in their own object in their own array.
function estimateGen(length, nodes) {
for (var i = 0; i < length; i++) {
const estimate = [];
let estimateVal = Math.random().toString(36).replace('0.','').slice(0,7);
estimate.push(estimateVal);
arr.push(estimate);
nodeGen(estimate, nodes)
}
}
// Adding x amount of nodes between 1 and 10 into each estimate sub array in their own objects.
function nodeGen(estimate, nodes) {
for (var i = 0; i < nodes; i++) {
let nodeID = Math.floor(Math.random() * 10) + 1;
estimate.push(nodeID);
}
}
// Calling the function and saying how many nodes per estimate we want.
estimateGen(5, 3);
console.log(arr);
From this code I now get the result:
[
[ 'p68xw8h', 5, 4, 6 ],
[ 'wn2yoee', 5, 4, 5 ],
[ '1w01tem', 9, 7, 4 ],
[ 'we3s53f', 8, 8, 8 ],
[ '5nrtp09', 3, 3, 8 ]
]
Would there be a way to count the number of times the values on the right appear and what 'estimate' ID at [0] it appears in?
Thank you.
First, let's redesign your input data and results to be a more useful format:
// input
[
{ nodes: [3, 4, 6], Estimate: '0jvyt8a' },
{ nodes: [4, 6, 3], Estimate: 'mc973fs' },
{ nodes: [4, 1, 3], Estimate: 'vwsfh8k' },
{ nodes: [4, 3, 5], Estimate: 'n6xzge3' },
{ nodes: [8, 7, 1], Estimate: 'v0jn7bh' }
];
// result
{
1: ["vwsfh8k", "v0jn7bh"],
3: ["0jvyt8a", "mc973fs", "vwsfh8k", "n6xzge3"],
...
]
Then the code would be:
const input = [
{ nodes: [3, 4, 6], Estimate: '0jvyt8a' },
{ nodes: [4, 6, 3], Estimate: 'mc973fs' },
{ nodes: [4, 1, 3], Estimate: 'vwsfh8k' },
{ nodes: [4, 3, 5], Estimate: 'n6xzge3' },
{ nodes: [8, 7, 1], Estimate: 'v0jn7bh' }
];
const result = {};
input.forEach(({
nodes,
Estimate: e
}) =>
nodes.forEach(n => {
if (!result[n]) {
result[n] = [];
}
result[n].push(e);
})
);
console.log(result);
You can create the data with:
// Making an empty array
const arr = [];
//Generating the estimate IDs and placing them all in their own object in their own array.
function estimateGen(length, nodes) {
for (var i = 0; i < length; i++) {
let estimateVal = Math.random().toString(36).replace('0.', '').slice(0, 7);
const estimate = {
Estimate: estimateVal,
nodes: []
}
arr.push(estimate);
nodeGen(estimate, nodes)
}
}
// Adding x amount of nodes between 1 and 10 into each estimate sub array in their own objects.
function nodeGen(estimate, nodes) {
for (var i = 0; i < nodes; i++) {
let nodeID = Math.floor(Math.random() * 10) + 1;
estimate.nodes.push(nodeID);
}
}
// Calling the function and saying how many nodes per estimate we want.
estimateGen(5, 3);
console.log(arr);
I've reformatted your array. The output is different, but you can still use it.
var arr = [
{ '0': 3 , '1': 4 , '2': 6 , 'Estimate:': '0jvyt8a' },
{ '0': 4 , '1': 6 , '2': 3 , 'Estimate:': 'mc973fs' },
{ '0': 4 , '1': 1 , '2': 3 , 'Estimate:': 'vwsfh8k' },
{ '0': 4 , '1': 3 , '2': 5 , 'Estimate:': 'n6xzge3' },
{ '0': 8 , '1': 7 , '2': 1 , 'Estimate:': 'v0jn7bh' }
];
var num = [1, 3, 4, 5, 6, 7, 8];
num = num.map(n =>
[n, ...(
arr.filter(a => [0, 1, 2].some(nm => a[nm] === n))
.map(v => v["Estimate:"])
)]);
console.log(num);
For getting a counting object you could take the values as key and estimates as key for the count of same values.
function estimateGen(length, nodes) {
var array = [];
for (var i = 0; i < length; i++) {
array.push([Math.random().toString(36).replace('0.','').slice(0,7), ...nodeGen(nodes)]);
}
return array;
}
function nodeGen(nodes) {
var result = [];
for (var i = 0; i < nodes; i++) {
result.push(Math.floor(Math.random() * 10) + 1);
}
return result;
}
function count(data) {
return data.reduce((r, [estimate, ...values]) => {
values.forEach(v => {
r[v] = r[v] || {};
r[v][estimate] = (r[v][estimate] || 0) + 1;
});
return r;
}, {});
}
var temp = estimateGen(5, 3);
console.log(temp);
console.log(count(temp));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Finding objects in a nested array along with their position

I've taken the following sample from a different question. And I am able to identify the object. But I also need to find our the position of that object. For example:
var arr = [{
Id: 1,
Categories: [{
Id: 1
},
{
Id: 2
},
]
},
{
Id: 2,
Categories: [{
Id: 100
},
{
Id: 200
},
]
}
]
If I want to find the object by the Id of the Categories, I can use the following:
var matches = [];
var needle = 100; // what to look for
arr.forEach(function(e) {
matches = matches.concat(e.Categories.filter(function(c) {
return (c.Id === needle);
}));
});
However, I also need to know the position of the object in the array. For example, if we are looking for object with Id = 100, then the above code will find the object, but how do I find that it's the second object in the main array, and the first object in the Categories array?
Thanks!
Well, if every object is unique (only in one of the categories), you can simply iterate over everything.
var arr = [{
Id: 1,
Categories: [{Id: 1},{Id: 2}]
},
{
Id: 2,
Categories: [{Id: 100},{Id: 200}]
}
];
var needle = 100;
var i = 0;
var j = 0;
arr.forEach(function(c) {
c.Categories.forEach(function(e) {
if(e.Id === needle) {
console.log("Entry is in position " + i + " of the categories and in position " + j + " in its category.");
}
j++;
});
j = 0;
i++;
});
function findInArray(needle /*object*/, haystack /*array of object*/){
let out = [];
for(let i = 0; i < haystack.lenght; i++) {
if(haystack[i].property == needle.property) {
out = {pos: i, obj: haystack[i]};
}
}
return out;
}
if you need the position and have to filter over an property of the object you can use a simple for loop. in this sample your result is an array of new object because there can be more mathches than 1 on the value of the property.
i hope it helps
Iterate over the array and set index in object where match found
var categoryGroups = [{
Id : 1,
Categories : [{
Id : 1
}, {
Id : 2
},
]
}, {
Id : 2,
Categories : [{
Id : 100
}, {
Id : 200
},
]
}
]
var filterVal = [];
var needle = 100;
for (var i = 0; i < categoryGroups.length; i++) {
var subCategory = categoryGroups[i]['Categories'];
for (var j = 0; j < subCategory.length; j++) {
if (subCategory[j]['Id'] == findId) {
filterVal.push({
catIndex : i,
subCatIndex : j,
id : needle
});
}
}
}
console.log(filterVal);
Here is solution using reduce:
var arr = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 }, ] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }, ] } ]
const findPositions = (id) => arr.reduce((r,c,i) => {
let indx = c.Categories.findIndex(({Id}) => Id == id)
return indx >=0 ? {mainIndex: i, categoryIndex: indx} : r
}, {})
console.log(findPositions(100)) // {mainIndex: 1, categoryIndex: 0}
console.log(findPositions(1)) // {mainIndex: 0, categoryIndex: 0}
console.log(findPositions(200)) // {mainIndex: 1, categoryIndex: 1}
console.log(findPositions(0)) // {}
Beside the given answers with fixt depth searh, you could take an recursive approach by checking the Categories property for nested structures.
function getPath(array, target) {
var path;
array.some(({ Id, Categories = [] }) => {
var temp;
if (Id === target) {
path = [Id];
return true;
}
temp = getPath(Categories, target);
if (temp) {
path = [Id, ...temp];
return true;
}
});
return path;
}
var array = [{ Id: 1, Categories: [{ Id: 1 }, { Id: 2 },] }, { Id: 2, Categories: [{ Id: 100 }, { Id: 200 }] }];
console.log(getPath(array, 100));
.as-console-wrapper { max-height: 100% !important; top: 0; }

Add a class to active slides

I have got an array of elements: [0, 1, 2, 3, 4, 5, 6, 7]. Also I have an array (this.state.currentSlides) of three numbers which is indicates to which element from first array I need to add a class: [0, 1, 2] or [3, 4, 5] or [5, 6, 7].
The buttons scroll to next or previous 3 slides.
The code below works only one time with first render. How to dynamically add a current class ('slide-current') to 3 of all elements?
checkClass(i) {
var className;
className = '';
for (var k = 0; k < this.state.currentSlides.length; k++) {
if (k == i) {
className = ' slide-current '
}
}
return className;
}
createSlides() {
var arr = [];
this.props.order.orders.map((item, i) =>{
arr.push(<div key={i} className={this.checkClass(i)}>element</div>);
});
return arr;
}
onNextClick() {
this.setState({
currentSlides: this.state.currentSlides.map((item, i) => {
item += 3;
return item })
})}
render() {
return <div>
{this.createSlides()}
<button onClick={ e => { this.onNextClick() }}>Next</button>
<button onClick={ e => { this.onPreviousClick() }}>Previous</button>
</div>
}
this.props.order.orders is the array of objects. For example:
[[{ title: 'Pizza'}],
[{ title: 'Pizza'}, { title: 'Cola'}, { title: 'Maffin'}],
[{ title: 'Maffin'}],
[{ title: 'Coffee'}],
[{ title: 'Pizza'}],
[{ title: 'Pizza'}, { title: 'Cola'}, { title: 'Maffin'}],
[{ title: 'Maffin'}],
[{ title: 'Coffee'}]];
You good with rest of the part. Just change below function to make it work.
Compare actual value i.e this.state.currentSlides[k] with currentSlide value i.e i. you are comparing index with value.
checkClass(i) {
var className;
className = '';
for (var k = 0; k < this.state.currentSlides.length; k++) {
if (this.state.currentSlides[k] == i) {
className = ' slide-current '
}
}
return className;
}

Categories

Resources