JavaScript比较、合并、从数组中设置数据以准备表格。

huangapple go评论66阅读模式
英文:

Javascript compare, merge, set data from arrays to prep for table

问题

以下是您提供的代码的翻译部分:

我正在为一个表格准备后端数据并希望以一种可以映射表格行的方式设置它表格的标题基于用于查询数据的日期范围始终为6个月的范围),然后我将其与数据进行比较并进行合并以设置初始对象但然后我需要与后端的另一个数组进行比较以使行完整

这是标题和数据数组
const headers = ["2022-7", "2022-8", "2022-9", "2022-10", "2022-11", "2022-12"]

const data = [
{
        "planDetails": {
            "goals": [
                {
                    "title": "Budget",
                    "frequency": 4
                },
                {
                    "title": "clean",
                    "frequency": 6
                }
            ]
        },
        "setVisits": [
            {
                "goals": [
                    {
                        "k": "clean",
                        "v": 2
                    },
                    {
                        "k": "Budget",
                        "v": 2
                    }
                ],
                "date": "2022-9"
            },
            {
                "goals": [
                    {
                        "k": "clean",
                        "v": 2
                    },
                    {
                        "k": "Budget",
                        "v": 2
                    }
                ],
                "date": "2022-10"
            },
            {
                "goals": [
                    {
                        "k": "Budget",
                        "v": 1
                    },
                    {
                        "k": "clean",
                        "v": 2
                    },
                ],
                "date": "2022-8"
            }
        ]
    }
]

然后是我采取的步骤
const output = data.shift()
console.log(output)

const newHeader = headers.map(i => new Date(i).toISOString())
/* console.log(newHeader) */

const visits = output.setVisits.map(i => { return {date: new Date(i.date).toISOString(), goals: i.goals}})
/* console.log(visits) */

const result = newHeader.map(item => {
/* console.log(item) */
  
    const info = visits.find(detail => detail.date === item);
    /* console.log(info) */
if (info) {
    return {
        date: item,
        goals: info.goals
    }
    } else {
    return {
    	date: item,
      goals: 0
    }
    }
})
result.sort((a,b) => a.date > b.date)

let finalArr = []

const next = output.planDetails.goals.forEach(i => {
	let newObj = {}
  /* console.log(i) */
 if ( result.find(a => a.goals.k === i.title)) {
 		newObj = {
    	goal: i.title,
      frequency: i.frequency,
      elem1: {
      	date: a[0].date,
        count: a[0].goals.v
      },
      elem2: {
      	date: a[1].date,
        count: a[1].goals.v
      }
    } 
/* 我只放了前6个元素的索引,以尝试在映射其余部分之前获得概念的证明 */
 } else if (!result.find(a => a.goals.k === i.title)) {
 		newObj = {
    	goal: i.title,
      frequency: i.frequency,
      elems: {
      	date: a[0].date,
        count: 0
      }
    }
 }
  finalArr.push(newObj)
})

console.log(finalArr)

希望这有助于理解您的代码。如果您有其他问题或需要进一步的帮助,请告诉我。

英文:

I'm prepping backend data for a table and want to get it set in a way so I can map out the table rows. The headers for the table is based on the date range that is used to query the data (always a 6 month spread), which I then compare and do a merge with the data to set up the initial objects, but then I need to compare with another array from the backend to make the row complete.

Here is the headers and data arrays:

const headers = [ "2022-7", "2022-8", "2022-9", "2022-10", "2022-11", "2022-12" ]
const data = [
{
"planDetails": {
"goals": [
{
"title": "Budget",
"frequency": 4
},
{
"title": "clean",
"frequency": 6
}
]
},
"setVisits": [
{
"goals": [
{
"k": "clean",
"v": 2
},
{
"k": "Budget",
"v": 2
}
],
"date": "2022-9"
},
{
"goals": [
{
"k": "clean",
"v": 2
},
{
"k": "Budget",
"v": 2
}
],
"date": "2022-10"
},
{
"goals": [
{
"k": "Budget",
"v": 1
},
{
"k": "clean",
"v": 2
},
],
"date": "2022-8"
}
]
}
]

And then the steps I've taken:

const output = data.shift()
console.log(output
)
const newHeader = headers.map(i => new Date(i).toISOString())
/* console.log(newHeader) */
const visits = output.setVisits.map(i => { return {date: new Date(i.date).toISOString(), goals: i.goals}})
/* console.log(visits) */
const result = newHeader.map(item => {
/* console.log(item) */
const info = visits.find(detail => detail.date === item);
/* console.log(info) */
if (info) {
return {
date: item,
goals: info.goals
}
} else {
return {
date: item,
goals: 0
}
}
})
result.sort((a,b) => a.date > b.date)
let finalArr = []
const next = output.planDetails.goals.forEach(i => {
let newObj = {}
/* console.log(i) */
if ( result.find(a => a.goals.k === i.title)) {
newObj = {
goal: i.title,
frequency: i.frequency,
elem1: {
date: a[0].date,
count: a[0].goals.v
},
elem2: {
date: a[1].date,
count: a[1].goals.v
}
} 
/* I've only put to the 2nd index of 6 to try and get the proof of concept down before mapping the rest */
} else if (!result.find(a => a.goals.k === i.title)) {
newObj = {
goal: i.title,
frequency: i.frequency,
elems: {
date: a[0].date,
count: 0
}
}
}
finalArr.push(newObj)
})
console.log(finalArr)

Its that last step that is off and javascript makes my head spin. I'm pretty certain theres a simple way to compare the 2 fields of the objects and map that out, providing a 0 if there is no matching field, but I'm getting no where.

My ideal final array would look like:

[
{goal: 'Budget', frequency: 4, elem1: {date: "2022-7", count: 1}, elem2: {date: "2022-8", count: 3}, elem3: {date: "2022-9", count: 0}, etc.}
{goal: 'clean', frequency: 2, elem1: {date: "2022-7", count: 1}, elem2: {date: "2022-8", count: 0}, elem3: {date: "2022-9", count: 2}, etc.}
]

Thanks in advance for any input, here's a link to the fiddle: https://jsfiddle.net/joznox/rwyL928a/45/

答案1

得分: 1

你可以首先使用 Array#reduce 为特定日期的每个目标创建一个频率查找表。然后,最终结果可以使用 Array#map 创建。

const headers=["2022-7","2022-8","2022-9","2022-10","2022-11","2022-12"],data=[{planDetails:{goals:[{title:"Budget",frequency:4},{title:"clean",frequency:6}]},setVisits:[{goals:[{k:"clean",v:2},{k:"Budget",v:2}],date:"2022-9"},{goals:[{k:"clean",v:2},{k:"Budget",v:2}],date:"2022-10"},{goals:[{k:"Budget",v:1},{k:"clean",v:2},],date:"2022-8"}]}];

const o = data.shift(); // or data[0] to not mutate data
const lookup = o.setVisits.reduce((acc, {date, goals}) => {
   goals.forEach(({k, v}) => (acc[date] ??= {})[k] = (acc[date][k] ?? 0) + v);
   return acc;
}, {});
const res = o.planDetails.goals.map(({title: goal, frequency}) => 
  ({goal, frequency, ...Object.fromEntries(headers
    .map((date, i) => [`elem${i+1}`, {date, count: lookup[date]?.[goal] ?? 0}]))}));
console.log(res);
.as-console-wrapper{max-height:100%!important}
英文:

You could first create a lookup table for the frequency of each goal for a particular date using Array#reduce. Then, the final result can be created with Array#map.

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const headers=[&quot;2022-7&quot;,&quot;2022-8&quot;,&quot;2022-9&quot;,&quot;2022-10&quot;,&quot;2022-11&quot;,&quot;2022-12&quot;],data=[{planDetails:{goals:[{title:&quot;Budget&quot;,frequency:4},{title:&quot;clean&quot;,frequency:6}]},setVisits:[{goals:[{k:&quot;clean&quot;,v:2},{k:&quot;Budget&quot;,v:2}],date:&quot;2022-9&quot;},{goals:[{k:&quot;clean&quot;,v:2},{k:&quot;Budget&quot;,v:2}],date:&quot;2022-10&quot;},{goals:[{k:&quot;Budget&quot;,v:1},{k:&quot;clean&quot;,v:2},],date:&quot;2022-8&quot;}]}];
const o = data.shift(); // or data[0] to not mutate data
const lookup = o.setVisits.reduce((acc, {date, goals}) =&gt; {
goals.forEach(({k, v}) =&gt; (acc[date] ??= {})[k] = (acc[date][k] ?? 0) + v);
return acc;
}, {});
const res = o.planDetails.goals.map(({title: goal, frequency}) =&gt; 
({goal, frequency, ...Object.fromEntries(headers
.map((date, i) =&gt; [`elem${i+1}`, {date, count: lookup[date]?.[goal] ?? 0}]))}));
console.log(res);

<!-- language: lang-css -->

.as-console-wrapper{max-height:100%!important}

<!-- end snippet -->

答案2

得分: 0

以下是您要翻译的内容:

另一种解决方案可能是首先整理您的数据,利用对象索引来汇总数据。

然后,一旦数据被汇总,为您的输出整理数据。

请注意,我已经将代码部分去除,只提供了翻译好的内容。如果您需要任何其他帮助,请随时告诉我。

英文:

Another solution may be to shape your data first, taking advantage of object indexes to aggregate the data.

const fields = headers.reduce((a,d)=&gt;{
    a[d] = 0;
    return a;
  },{});

let final= {};
for(let visit of data.pop().setVisits){
  let date = new Date(visit.date)
    .toISOString()
    .substr(0,7)
    .split(&#39;-&#39;)
    .map(d=&gt;Number.parseInt(d))
    .join(&#39;-&#39;)
    ;
  for(let goal of visit.goals){
    let v = goal.v;
    goal = goal.k;
  	final[goal] ??= {
      frequency:0,
      fields:Object.assign({},fields)
    };
    final[goal].frequency+=v;
    final[goal].fields[date]+=v;
  }
}
console.log(final);

Then once the data is aggregated, shape it for your output.

let finalArr = Object.entries(final).map(d=&gt;{
  let row = Object.entries(d[1].fields)
    .sort(d=&gt;{ return new Date(d[0])-new Date(d[1]); })
    .map (d=&gt;{ return {date: d[0], count: d[1]}; })
    .reduce((a,d,i)=&gt;{ a[`elem${i+1}`] = d; return a;}, {})
    ;
  row.goal = d[0];
  row.frequency = d[1].frequency;
  return row;
});
console.log(finalArr);

huangapple
  • 本文由 发表于 2023年6月1日 07:30:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/76377851.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定