Javascript 对象的迭代整合

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

Javascript consolidate iteration of objects

问题

我有一个动态对象myObj,如下所示:

  1. {
  2. "section-1": {
  3. "id": "section-1",
  4. "fields": [
  5. {
  6. "id": "field1",
  7. "items": [
  8. {
  9. "display": "Select",
  10. "value": "SELECT"
  11. },
  12. {
  13. "display": "A 1",
  14. "value": "A1"
  15. },
  16. {
  17. "display": "A 2",
  18. "value": "A2"
  19. }
  20. ],
  21. "value": "A1"
  22. },
  23. {
  24. "id": "field2",
  25. "items": [],
  26. "value": "Field 2"
  27. }
  28. ]
  29. },
  30. "section-2": {
  31. "id": "section-2",
  32. "fields": []
  33. },
  34. "section-3": {
  35. "id": "section-3",
  36. "fields": []
  37. }
  38. }

这些部分和字段都来自API响应,因此可以有n个部分和n个字段。

我想从这些对象中提取“myDefaults”,它是“value”属性。

到目前为止,我正在手动迭代每个部分,然后提取字段值到myDefaults,如下所示。
但是,我想知道是否可以以更好的方式编写这个逻辑(可能是ES6的方式),考虑到所有部分的结构都相似(只是可以有n个部分,其中包含n个字段)。

  1. const section1 = myObj?.sections['section-1'];
  2. const section2 = myObj?.sections['section-2'];
  3. let myDefaults = {};
  4. section1.fields.forEach((field) => {
  5. myDefaults[field.id] = field.value;
  6. if (field.items && field.items.length > 0) {
  7. myDefaults[field.id] = field.items.find(item => item.value === field.value);
  8. }
  9. });
  10. section2.fields.forEach((field) => {
  11. myDefaults[field.id] = field.value;
  12. if (field.items && field.items.length > 0) {
  13. myDefaults[field.id] = field.items.find(item => item.value === field.value);
  14. }
  15. });
英文:

I have a dynamic object myObj as below

  1. {
  2. "section-1": {
  3. "id": "section-1",
  4. "fields": [
  5. {
  6. "id": "field1",
  7. "items": [
  8. {
  9. "display": "Select",
  10. "value": "SELECT"
  11. },
  12. {
  13. "display": "A 1",
  14. "value": "A1"
  15. },
  16. {
  17. "display": "A 2",
  18. "value": "A2"
  19. }
  20. ],
  21. "value": "A1"
  22. }, {
  23. "id": "field2",
  24. "items": [],
  25. "value": "Field 2"
  26. }
  27. ]
  28. },
  29. "section-2": {
  30. "id": "section-2",
  31. "fields": []
  32. },
  33. section-3": {
  34. "id": "section-3",
  35. "fields": []
  36. }
  37. }

The sections and fields are both dynamic from API response. So, it can have n number of sections and n number of fields.

I want to extract "myDefaults" from within these objects which is the "value" attribute.

As of now, I am manually iterating through each section and then extracting field.value into myDefaults as below.
However, I am wondering if there can be any better way of writing this logic (probably ES6 way of writing), considering all the sections would have similar structure (just that there can be n number of sections with n number of fields within them)

  1. const section1 = myObj?.sections['section-1'];
  2. const section2 = myObj?.sections['section-2'];
  3. let myDefaults = {};
  4. section1.fields.forEach((field) => {
  5. myDefaults[field.id] = field.value;
  6. if (field.items && field.items.length > 0) {
  7. myDefaults[field.id] = field.items.find(item => item.value === field.value);
  8. }
  9. });
  10. section2.fields.forEach((field) => {
  11. myDefaults[field.id] = field.value;
  12. if (field.items && field.items.length > 0) {
  13. myDefaults[field.id] = field.items.find(item => item.value === field.value);
  14. }
  15. });

答案1

得分: 3

你可以使用 Object.values 来避免硬编码部分名称。

此代码获取所有部分,然后对每个部分的字段进行访问。它在项目列表中查找所选值。是否找到匹配项决定了我们是只使用该值还是一个包含值和显示属性的对象。

最后,我们使用 Object.fromEntries 将所有 [key, value] 条目合并为一个单一对象。

英文:

You can use Object.values to avoid hard-coding the section names.

This code gets all sections, then for each section visits each field. It looks up the selected value in the list of items. Whether a match is found determines whether we just use the value or an object containing the value and the display property.

Finally, we use Object.fromEntries to merge all of the [key, value] entries into a single object.

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

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

  1. const myObj = {&quot;sections&quot;:{&quot;section-1&quot;:{&quot;id&quot;:&quot;section-1&quot;,&quot;fields&quot;:[{&quot;id&quot;:&quot;field1&quot;,&quot;items&quot;:[{&quot;display&quot;:&quot;Select&quot;,&quot;value&quot;:&quot;SELECT&quot;},{&quot;display&quot;:&quot;A 1&quot;,&quot;value&quot;:&quot;A1&quot;},{&quot;display&quot;:&quot;A 2&quot;,&quot;value&quot;:&quot;A2&quot;}],&quot;value&quot;:&quot;A1&quot;},{&quot;id&quot;:&quot;field2&quot;,&quot;items&quot;:[],&quot;value&quot;:&quot;Field 2&quot;}]},&quot;section-2&quot;:{&quot;id&quot;:&quot;section-2&quot;,&quot;fields&quot;:[]},&quot;section-3&quot;:{&quot;id&quot;:&quot;section-3&quot;,&quot;fields&quot;:[]}}};
  2. console.log(
  3. Object.fromEntries(Object.values(myObj.sections)
  4. .flatMap(i =&gt; i.fields.map(({id, items, value}) =&gt; [
  5. id,
  6. items?.find(item =&gt; item.value===value) ?? value
  7. ]))
  8. )
  9. )

<!-- end snippet -->

答案2

得分: 1

这适用于您在示例中提供的对象。您可以编辑它以适应您的业务需求。干杯!

  1. Object.keys(myObj)
  2. .map(key => myObj[key].fields)
  3. .flat()
  4. .reduce((result, fieldItem) => {
  5. const { id, items, value } = fieldItem;
  6. result[id] = items?.length ?
  7. items.find(i => i.value == value)
  8. : value;
  9. return result;
  10. }, {})

P.S. 我还没有考虑到任何边缘情况 xD

英文:

This works for the object that you gave in the example. You can edit it to suit your business needs. Cheers!

  1. Object.keys(myObj)
  2. .map(key=&gt; myObj[key].fields)
  3. .flat()
  4. .reduce((result, fieldItem)=&gt;{
  5. const {id, items, value } = fieldItem
  6. result[id] = items?.length ?
  7. items.find(i =&gt; i.value == value)
  8. : value;
  9. return result;
  10. }, {})

P.S. I haven't thought of any edge cases though xD

答案3

得分: 1

I have used your logic but used it in combination with Object.entries and Array#reduce:

  1. let myObj = {
  2. sections: {
  3. "section-1": {
  4. id: "section-1",
  5. fields: [
  6. {
  7. id: "field1",
  8. items: [
  9. { display: "Select", value: "SELECT" },
  10. { display: "A 1", value: "A1" },
  11. { display: "A 2", value: "A2" }
  12. ],
  13. value: "A1"
  14. },
  15. {
  16. id: "field2",
  17. items: [],
  18. value: "Field 2"
  19. }
  20. ],
  21. value: "A1"
  22. },
  23. "section-2": {
  24. id: "section-2",
  25. fields: []
  26. },
  27. "section-3": {
  28. id: "section-3",
  29. fields: []
  30. }
  31. }
  32. };
  33. let result = Object.entries(myObj.sections).reduce((acc, [keys, values]) => {
  34. values.fields.forEach((field) => {
  35. acc[field.id] = field.value;
  36. if (field.items && field.items.length > 0) {
  37. acc[field.id] = field.items.find(item => item.value === field.value);
  38. }
  39. });
  40. return acc;
  41. }, {});
  42. console.log(result);
英文:

I have used your logic but used it in combination with Object.entries and Array#reduce:

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

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

  1. let myObj={sections:{&quot;section-1&quot;:{id:&quot;section-1&quot;,fields:[{id:&quot;field1&quot;,items:[{display:&quot;Select&quot;,value:&quot;SELECT&quot;},{display:&quot;A 1&quot;,value:&quot;A1&quot;},{display:&quot;A 2&quot;,value:&quot;A2&quot;}],value:&quot;A1&quot;},{id:&quot;field2&quot;,items:[],value:&quot;Field 2&quot;}]},&quot;section-2&quot;:{id:&quot;section-2&quot;,fields:[]},&quot;section-3&quot;:{id:&quot;section-3&quot;,fields:[]}}};
  2. let result = Object.entries(myObj.sections).reduce((acc, [keys, values]) =&gt; {
  3. values.fields.forEach((field) =&gt; {
  4. acc[field.id] = field.value;
  5. if (field.items &amp;&amp; field.items.length &gt; 0) {
  6. acc[field.id] = field.items.find(item =&gt; item.value === field.value);
  7. }
  8. });
  9. return acc
  10. }, {})
  11. console.log(result)

<!-- end snippet -->

huangapple
  • 本文由 发表于 2023年6月15日 12:44:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/76479183.html
匿名

发表评论

匿名网友

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

确定