Remap structure parent object base on child array data and length object - arrays

I am trying remap structure data parent base on child array data and length. It's possible to do? Structure array it's good or i need change array object from backend?
There is no id in child arrays.
This is what i have done
this.arrays = [
{
id: '1',
idbid: '0000000001618',
name: 'ebi',
rate: '400',
bid: [
{
bid: 10000,
date: '2022/12/12',
value: 5000,
},
{
bid: 10000,
date: '2022/12/14',
value: 8100,
},
{
bid: 15000,
date: '2022/12/15',
value: 8100,
},
],
},
{
id: '2',
idbid: '0000000001618',
name: 'bio',
rate: '100',
bid: [
{
bid: 8000,
date: '2022/12/13',
value: 8000,
},
],
},
];
// merge all item bid in child array
let allVal: any = [];
allVal = allVal.concat(this.arrays.map((data) => data.bid).flat());
console.log(allVal);
// get unique bid
var uniqueData = [];
allVal.forEach((item) => {
let count = uniqueData.filter((x) => x.value == item.value).length;
if (count == 0) {
uniqueData.push(item);
}
});
console.log(uniqueData);
// find and merge into parent array
const newArrays = uniqueData.map((obj) => {
return this.arrays.find((data) =>
data.bid.some((val) => val.value == obj.value)
);
});
console.log(newArrays);
// remap structure custom arrays of parent
const remapArrays = newArrays.map((obj, index) => {
return {
id: index + 1,
idbid: obj.idbid,
name: obj.name,
rate: obj.rate,
bid: obj.bid[index]?.bid,
date: obj.bid[index]?.date,
value: obj.bid[index]?.value,
};
});
console.log(remapArrays);
but the result is like this
[
{
id: '1',
idbid: '0000000001618',
name: 'ebi',
rate: '400',
bid: 10000,
date: '2022/12/12',
value: 5000,
},
{
id: '2',
idbid: '0000000001618',
name: 'bio',
rate: '100',
bid: 10000,
date: '2022/12/13',
value: 8100,
},
{
id: '3',
idbid: '0000000001618',
name: 'ebi',
rate: '400',
bid: undefined,
date: undefined,
value: undefined,
},
];
and here is what expected output
// output final that exptected
this.customArrays = [
{
id: '1',
idbid: '0000000001618',
name: 'ebi',
rate: '400',
bid: 10000,
date: '2022/12/12',
value: 5000,
},
{
id: '2',
idbid: '0000000001618',
name: 'bio',
rate: '100',
bid: 8000,
date: '2022/12/13',
value: 8000,
},
{
id: '3',
idbid: '0000000001618',
name: 'ebi',
rate: '400',
bid: 15000,
date: '2022/12/15',
value: 8100,
},
];
Here is link for test Stackblitz

There are some things that should be defined more clearly in the question:
Do we expect the value of "idbid" to be the same across all elements of the original array?
Should the resulting array have the first date of each unique bid?
In my answer, I'll be assuming that the answer is "yes" to both.
In the beginning, when merging all child arrays:
allVal.concat(this.arrays.map((data) => data.bid).flat());
We're losing the values that are unique to each parent element: for example, the value of "rate" is "400" for the first parent element and "100" for the second. So before flattening, we need to map each of the bid arrays, so each child element includes the data from the parent element:
// merge all item bids in child arrays
const allVal = this.arrays
.map((dataWithBids) => {
const { id, idbid, name, rate, bid: bidArr } = dataWithBids;
// add data from the parent element to each bid
return bidArr.map((bidData) => ({
idbid,
name,
rate,
...bidData,
}));
})
.flat();
In the following step, getting only unique values can be done the same way as you did, or using the array some method:
// get unique bids
const uniqueData = [];
allVal.forEach((item) => {
const exists = uniqueData.some((x) => x.value == item.value);
if (!exists) {
uniqueData.push(item);
}
});
At this point we have the correct values, and we need to order them by date and add ids:
const sorted = uniqueData
// sort by date
.sort(
(bidData1, bidData2) =>
Date.parse(bidData1.date) - Date.parse(bidData2.date)
)
// add ids
.map((bidData, index) => ({
...bidData,
id: index + 1 // or (index + 1).toString(),
}));
The result of the above sorted array matches the expected output.

Related

Mapping through nested arrays in es6 javascript

I have a simple array that I want to group it's objects by date so I used this function
const groupedDates= Object.entries(
items.reduce((acc, { product, price, type, date }) => {
if (!acc[date]) {
acc[date] = [];
}
acc[date].push({ product, price, type date });
return acc;
}, {})
).map(([date, items]) => ({ date, items }));
the array
const items = [
{
id: 1,
product: "milk",
price: 10,
type: "drink"
date: "01/01/2022",
},
{
id: 2,
product: "coca",
price: 11,
type: "drink"
date: "01/01/2022",
},
{
id: 3,
product: "pepsi",
price: 20,
type: "drink"
date: "01/01/2024",
},
{
id: 4,
product: "carrots",
price: 30,
type: "food",
date: "01/01/2023",
},
];
I got this result
{
0: [
date: 01/01/2022,
items : [
0 : {
id: 1,
product: "milk",
price: 10,
type: "drink"
date: "01/01/2022"
}
1 : {
id: 2,
product: "coca",
price: 11,
type: "drink"
date: "01/01/2022",
}
],
1: [
date: "01/01/2024",
items : [
0 : {
id: 3,
product: "pepsi",
price: 20,
type: "drink"
date: "01/01/2024",
}
],
2: [
date: "01/01/2023",
items: [
0:{
id: 4,
product: "carrots",
price: 30,
type: "food",
date: "01/01/2023"
}
]
]
}
Issue:
I cannot seem to figure out how to access items1 when it exists.
What I have tried
is the map below but it only returns the first level of items which is 0 and if I do items1 it returns an error because not all arrays have a second item.
{groupedDates.map((obj) => (
{obj.items[0].product}))}
UPDATE
I'd also like to get the total for each date so I can have a card that has the Date + The total + each item and it's individual price. After getting some help from #Nick, I've managed to output the date, the item and it's price, now I'm still missing the total price for the date.
You need to iterate the items in each obj to get the list of products:
const items = [
{ id: 1, product: "milk", price: 10, type: "drink", date: "01/01/2022" },
{ id: 2, product: "coca", price: 11, type: "drink", date: "01/01/2022" },
{ id: 3, product: "pepsi", price: 20, type: "drink", date: "01/01/2024" },
{ id: 4, product: "carrots", price: 30, type: "food", date: "01/01/2023" },
];
const groupedDates = Object.entries(
items.reduce((acc, { product, price, type, date }) => {
if (!acc[date]) {
acc[date] = [];
}
acc[date].push({ product, price, type, date });
return acc;
}, {})
).map(([date, items]) => ({ date, items }));
const allProducts = groupedDates.map((obj) => obj.items.map(i => i.product))
console.log(allProducts)
const totalsByDate = groupedDates.map(({ date, items }) => (
{ [date] : items.reduce((acc, item) => acc + item.price, 0) }
))
console.log(totalsByDate)
.as-console-wrapper { max-height:100% !important; top 0 }
Note I would make groupedDates an object with its keys being the dates; that will make looking up data for a given date much easier. For example:
const items = [
{ id: 1, product: "milk", price: 10, type: "drink", date: "01/01/2022" },
{ id: 2, product: "coca", price: 11, type: "drink", date: "01/01/2022" },
{ id: 3, product: "pepsi", price: 20, type: "drink", date: "01/01/2024" },
{ id: 4, product: "carrots", price: 30, type: "food", date: "01/01/2023" },
];
const groupedDates = items.reduce((acc, { date, ...rest }) => {
acc[date] = (acc[date] || []).concat({ ...rest })
return acc;
}, {})
console.log(groupedDates)
const allProducts = Object.values(groupedDates)
.flatMap(arr => arr.map(obj => obj.product))
console.log(allProducts)
const totalsByDate = Object.entries(groupedDates).map(([ date, items ]) => (
{ [date] : items.reduce((acc, item) => acc + item.price, 0) }
))
console.log(totalsByDate)
.as-console-wrapper { max-height:100% !important; top 0; }

How to Change Data in React

I want to create data from DATA to OPTIONS.
const DATA = [
{ name: 'aaa', id: 'happy' },
{ name: 'bbb', id: 'time' },
{ name: 'ccc', id: 'party' },
];
const OPTIONS =[{value:'aaa', label:'aaa'},
{value:'bbb', label:'bbb'},
{value:'ccc', label:'ccc'},
]
I need only name value in DATA.
so, using name value, I want to create OPTIONS.
Fuction Test(){
const DATA = [
{ name: 'aaa', id: 'happy' },
{ name: 'bbb', id: 'time' },
{ name: 'ccc', id: 'party' },
];
const OPTIONS =[{value:'aaa', label:'aaa'},
{value:'bbb', label:'bbb'},
{value:'ccc', label:'ccc'},
]
}
let newObject=[];
const createData = () => {
const arr = selectMainId.data.map(data => data.name);
arr.map(data => newObject.push({ value: data, label: data }));
console.log('newObj:', newObject);
};
console.log('newObj1:', newObject))
this case, I can get OPTIONS same data.
so, I can get newObject in createData console.
but I can't get newObject in Test console.
I don't know this issue.
Do you know effective way?
please help me.
The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.
Clean and simplest way:
const DATA = [
{ name: 'aaa', id: 'happy' },
{ name: 'bbb', id: 'time' },
{ name: 'ccc', id: 'party' },
];
const OPTIONS = DATA.map(x => ({value: x.name, label: x.name }));
console.log(OPTIONS);
You just need to do
const createData = (data) => {
return data.map(d => ({name: data.name, label: data.name}))
};
const option = createData(data)

Get 100% with rounded percentages of objects values in an array

I have an array of objects, and a value of the objects is a percent. Is there a way to round those values and still get 100% if added?
const items = [
{
name: 'Something',
value: 20.4
},
{
name: 'something else',
value: 36.6
},
{
name: 'another thing',
value: 21.5
},
{
name: 'other item',
value: 21.5
}
];
and return something like this
const items = [
{
name: 'Something',
value: 20
},
{
name: 'something else',
value: 37
},
{
name: 'another thing',
value: 21
},
{
name: 'other item',
value: 22
}
];
One way to achieve this is to iterate over the array, maintaining a rolling sum of the rounded values and then setting the last value in the array to 100 - sum:
const items = [
{ name: 'Something', value: 20.4 },
{ name: 'something else', value: 36.6 },
{ name: 'another thing', value: 21.5 },
{ name: 'other item', value: 21.5 }
];
let sum = 0;
const rounded = items.map(({name, value}, i) => {
if (i == items.length - 1) {
return { name, value: 100 - sum };
}
value = Math.round(value);
sum = sum + value;
return { name, value };
});
console.log(rounded);

React filter on item in array inside array

I am trying to return a filtered list in a mobx store but I cant figure out how the filter function properly works. I have a array that looks like this
#observable files = ([
{
id: '1',
fileType: 'Document',
files: [
{
name: 'test1',
size: '64kb',
date: '2018-01-19'
},
{
name: 'test2',
size: '94kb',
date: '2018-01-19'
}
]
},
{
id: '2',
fileType: 'List',
files: [
{
name: 'test3',
size: '64kb',
date: '2018-01-19'
},
{
name: 'test4',
size: '94kb',
date: '2018-01-19'
},
{
name: 'test5',
size: '94kb',
date: '2018-01-19'
}
]
} and so on...
I want to be able to filter on all names this.files[x].files[x].name
and then return the result. If I set the "What to put here" to this.files[0].files[0].name I am able to filter on the first entry of name. But how can i filter dynamically on all names?
#observable filter = ""
#computed get filteredFiles(){
var matchesFilter = new RegExp(this.filter, "i")
var filtered = this.files.filter(file => !this.filter || matchesFilter.test(What to put here?))
return filtered
}
Change matchesFilter.test(What to put here?) to
file.files.some(nestedfile=>matchesFilter.test(nestedFile.name))
if you want to also filter the inner list of files to only those that match then you need to .map the array
var filtered = this.files
.filter(file =>
!this.filter || file.files.some(nestedfile => matchesFilter.test(nestedFile.name)))
.map(file => ({ ...file,
files: file.files.filter(nesstedFile => matchesFilter.test(nestedFile.name))
}));

Javascript arrays: How to remove the all matched elements which are contained in another array

I have 2 javascript arrays which are a, b and I want to remove the common elements from the array a.
Can you please help on this.
var a = [{
name: 'java',
id: '1'
},
{
name: 'php',
id: '2'
},
{
name: 'ruby',
id: '3'
},
{
name: 'phyton',
id: '4'
}
];
var b = [{
name: 'java',
id: '1'
},
{
name: 'php',
id: '2'
}
];
It's basically a simple filter operation. I'd take the ids from b into an array, then filter by those elements
var a = [{
name: 'java',
id: '1'
},
{
name: 'php',
id: '2'
},
{
name: 'ruby',
id: '3'
},
{
name: 'phyton',
id: '4'
}
];
var b = [{
name: 'java',
id: '1'
},
{
name: 'php',
id: '2'
}
];
const exists = b.map(e => e.id);
const res = a.filter(e => !exists.includes(e.id));
console.log(res);

Resources