How to chunk an object into smaller objects - javascript

The goal is to break an object of unknown length and shape into small objects 3 elements each. Only vanilla JS solution; I don't want to use _.pick etc.
Example of large object:
const data = {
someFirstKey: 'someFirstVal',
someSecondKey: 'someSecondVal',
...
someLastKey: 'someLastVal'
}
Desired chunk with 3 keys:
{someKey0: 'someVal0', someKey1: 'someVal1', someKey2, 'someVal2'}

Based on the comments, it seems like you are actually looking for a way to split an object up into several smaller objects. I would approach that like this:
const data = {a:1,b:2,c:3,d:4,e:5,f:6,g:7};
const chunk_size = 3, chunks = [];
for ( const cols = Object.entries( data ); cols.length; )
chunks.push( cols.splice(0, chunk_size).reduce( (o,[k,v])=>(o[k]=v,o), {}));
console.log( chunks );

Ok, so this might not be the most efficient way, but it works on my box. ;)
const data = {} // fill in your data here
const keys = Object.keys(data); // gets you the keys from your obj.
const numberOfWholeParts = Math.floor( keys.length / 3 ); // or whatever your size limit is
const remainder = keys.length % 2; // keys left after all whole parts are filled
const arrayOfParts = [];
for(let i=0;i<numberOfWholeParts;i++) {
const obj = {};
const keySegment = keys.slice(i*3, i*3+3);
for(let j=0; j<3; j++) {
obj[keySegment[j]] = data[keySegment[j]];
}
arrayOfParts.push(obj);
}
if(remainder > 0){
const obj = {};
let remainingKeys = keys.slice(-remainder)
for(let i=0; i<remainingKeys.length;i++) {
obj[remainingKeys[i]] = data[remainingKeys[i]];
}
arrayOfParts.push(obj);
}

Using Object.fromEntries:
const entries = Object.entries(data);
const grouped = [];
for (let i = 0; i < entries.length; i++) {
if (i % groupSize === 0) {
grouped.push([entries[i]]);
} else {
grouped[Math.floor(i / groupSize)].push(entries[i]);
}
}
const chunks = grouped.map(o => Object.fromEntries(o));

Using Object destructuring
const { someKey0, someKey1, someKey2 } = data
const newData = {
someKey0,
someKey1,
someKey2
}

Related

Push in array only values ​that contain a certain string

I would like only data containing a certain string to be sent from my array to another array
for example
test=something
test1=something
test=testsadsad
If my array contains test=
My new array will be ['something', 'testsadsad']
This is my code.
let data = Object.values(args);
let serializedData = data.join("\n");
let newArray = [];
for (let i = 0; i < data.length; i++) {
if (data[i].includes("test=") === true) {
console.log(data[i])
newArray.push(data[i].split("test="));
}
}
You can modify your logic like this
//simulated data
const data = [
"test=something",
"test1=something",
"test=testsadsad",
]
let newArray = [];
for (let i = 0; i < data.length; i++) {
//`key` is `test` and `value` is `something`
const [key, value] = data[i].split("=") //splitted by `=`
if (key === "test") {
newArray.push(value);
}
}
console.log(newArray)
You are not formatting the data correctly when pushing onto the array.
let data = Object.values(args);
let newArray = [];
for (let i = 0; i < data.length; i++) {
if (data[i].includes("test=") === true) {
console.log(data[i])
// Note It looks like your problem is here
newArray.push(data[i].replace("test=", ''));
}
}
If your input array is data then this will return the desired output:
let output = data
.filter(item => item.includes("test="))
.map(item => item.split("test=")[1])
This filters the array by selecting all items that include test= and then maps each result to the substring after test=.

Javascript split strings in array on specific index

I have this array of strings.
const numbersArray = ['1000','10000','100000']
My goal is to split each one of them on specific index for example: output of 1000 should be 1,000 and etc...
Here is what i have right now:
const splitArrayHandler = (arr) =>{
for (let i = 0; i < arr.length; i++) {
let indexOfSymbol = Math.round(arr[i].length / 3)
return splitAtIndex(arr[i],indexOfSymbol)
}
}
const splitAtIndex = (value,index) => {
return value.substring(0,index) + ',' + value.substring(index)
}
splitArrayHandler(numbersArray)
The first function splitArrayHandler loops through my array,finds specific index of the symbol in the string and then function splitAtIndex does the rest of the hard work.
The problem is only first element of the string is passing to the splitAtIndexfunction and I dont understand why. any suggestions please?
const numbersArray = ['1000','10000','100000']
const splitArrayHandler = (arr) =>{
for (let i = 0; i < arr.length; i++) {
let indexOfSymbol = Math.round(arr[i].length / 3)
return splitAtIndex(arr[i],indexOfSymbol)
}
}
const splitAtIndex = (value,index) => {
return value.substring(0,index) + ',' + value.substring(index)
}
splitArrayHandler(numbersArray)
Use Intl.NumberFormat for the job. No need for string parsing / manipulating:
const numbersArray = ['1000', '10000', '100000', '654654686156', '1000.66', '10e14', '0xFFFF'];
const format = new Intl.NumberFormat('en-US').format;
const formattedNumbers = numbersArray.map(Number).map(format);
console.log(formattedNumbers);
You are breaking the loop by returning the splitAtIndex function. Create another array and push the results to it.
const splitArrayHandler = (arr) =>{
let arr2 = []
for (let i = 0; i < arr.length; i++) {
let indexOfSymbol = Math.round(arr[i].length / 3)
arr2.push(splitAtIndex(arr[i],indexOfSymbol))
}
return arr2
}
You might use regular expression and map function (though there is no real difference between map and hard coded loop)
const numbersArray = ['1000','10000','100000']
function addComa(x) {
return x.replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}
const resolved = numbersArray.map(addComma)
console.log(resolved) // ['1,000','10,000','100,000']

How to split an array in many others arrays with two specific sizes?

I'm trying to find out if there is a way in splitting an array into many others arrays, but these arrays should have a length of 4 and 8. Like:
const someArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,23,24,25];
output newArray = [[1,2,3,4],
[5,6,7,8,9,10,11,12],
[13,14,15,16],
[17,18,19,20,21,22,23,24],
[25]];
I've seen many solutions to chunk into specific single sizes like:
export const chunk = (array, size) => {
const chunkedArr = [];
let copiedArr = [...array];
const numOfChild = Math.ceil(copiedArr.length / size);
for (let i = 0; i < numOfChild; i++) {
chunkedArr.push(copiedArr.splice(0, size));
}
return chunkedArr;
};
which I've tried to "adapt" for my requirements, but had no success.
Any help?
Cheers!
A simple implementation consuming the array with a recursive function:
const someArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,23,24,25];
const iter = (sliceLen, arr, acc = []) =>
arr.length <= sliceLen
? [...acc, arr.slice(0, sliceLen)]
: iter(sliceLen === 4 ? 8 : 4, arr.slice(sliceLen), [...acc, arr.slice(0, sliceLen)])
const r = iter(4, someArray)
console.log(r)
You can use Array.slice() along with appropriate indices to achieve this.
const someArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,23,24,25];
let i = 0;
let step = 4;
const newArray = [];
while(i < someArray.length) {
newArray.push(someArray.slice(i, i + step));
i += step;
step = step == 4 ? 8 : 4;
}
console.log(newArray);
One approach to this would be to just swap back and forth between the chunk size for the iteration.
const someArray = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,23,24,25];
console.log(
chunk(someArray, 4, 8)
);
function chunk(input, size1, size2){
const output = [];
let chunkSize = size1;
for (let i = 0; i < input.length;) {
output.push(input.slice(i).slice(0, chunkSize));
i += chunkSize;
chunkSize = (chunkSize === size1 ? size2 : size1);
}
return output;
}

Extract JSON object from each file add it to the array

I have 4 links, each of them containing one, distinct JSON object. I want to fetch and then place all of them inside of the empty array.
I came up with this(I omited async/await):
let arr = [];
let iter = 0;
const FIXED_QUANTITY = 4;
while(iter < FIXED_QUANTITY) {
const res = axios.get(`/data/${iter}.json`);
arr = [...arr, res.data.body];
iter++;
}
And my question is - is it possible to make this code a bit more elegant, perhaps using higher order functions?
You could try something like this maybe?
const urls = [];
const FIXED_QUANTITY = 4;
const iter = 4;
while (iter < FIXED_QUANTITY) {
urls.push(`/data/${iter}.json`);
}
const arr = await Promise.all([...urls.map(url => axios.get(url))]).map(
res => res.data.body
);
You can use the function Array.from as follow:
let arr = Array.from({length: FIXED_QUANTITY}, async (_, iter) => (await axios.get(`/data/${iter}.json`)).data.body);
This approach generates an array with the following structure:
[{}, {}, ..., {}]

Javascript alphabetical grouping

I have a json array of objects that look like this: {id:'the id', name:'the name'}; and I need to loop over the array and group each object alphabetically by it's name attribute. Is there a way to do this without using a switch / if statement with every letter in it?
What I don't want to do is something like this:
if(data[i].name..slice(0, 1) == 'a') {
...
}
It's a large array, with almost a 1,000 objects in it. My goal is eventually append them to a dive so it looks something like this:
4
4 pints
4 biscuits
A
Apple
Alex
Adam
B
Bob
Billy
you can loop throught your collections like this:
var groupedCollection = {};
for(...){//loop throug collection
var firstLetter = data[i].charAt(0);
if(groupedCollection[firstLetter] == undefined){
groupedCollection[firstLetter] = [];
}
groupedCollection[firstLetter].push(data[i]);
}
//groupedCollection now contait data in the form of {a: [], b:[], etc...}
Bubble sort will do this job for you. Example:
// sample array
var myArr = [
{id:"00", name:"Billy"},
{id:"00", name:"Apple"},
{id:"00", name:"4 biscuits"},
{id:"00", name:"Adam"},
{id:"00", name:"Alex"},
{id:"00", name:"4 pints"},
{id:"00", name:"Bob"}
];
// standard bubble sort algorithm
function bubbleSortByName(arr) {
for (var x = 0; x < arr.length; x++) {
for(var y = 0; y < arr.length-1; y++) {
// compare arr[].name.toLowerCase() i.e. b > a
if(arr[y].name.toLowerCase() > arr[y+1].name.toLowerCase()) {
var tmp = arr[y+1];
arr[y+1] = arr[y];
arr[y] = tmp;
}
}
}
return arr;
}
// sort the array
var sortedArr = bubbleSortByName(myArr);
// print the results
for (var i=0; i<sortedArr.length; i++)
document.write(sortedArr[i].name+"<br/>");
Or the same idea with an insertion sort algorithm:
// standard insertion sort algorithm
function insertionSortByName(arr) {
for(var j = 1; j < arr.length; j++) {
var key = arr[j];
var i = j - 1;
while(i >= 0 && arr[i].name.toLowerCase() > key.name.toLowerCase()) {
arr[i+1] = arr[i];
i = i - 1;
}
arr[i+1] = key;
}
return arr;
}
ES7 syntax
const sortAndGroup = async () => {
const sortedData = data.sort();
const reducedData = sortedData.reduce((items, dataElement) => {
if (!items.find(item => item.header === dataElement.charAt(0))) {
items.push({ header: dataElement.charAt(0) });
}
items.push({ name: dataElement });
return items;
}, []);
return reducedData.map(item => item.header || item.name);
};
sortAndGroup().then(result => console.log(result));

Categories

Resources