admin管理员组

文章数量:1291009

I have the following input:

 schema: [{
    fields: [{
      name: 'name',
      type: 'text',
      col: 10,
      value: ''
    }, {
      name: 'description',
      type: 'text',
      col: 2,
      value: ''
    }]
  }, {
    fields: [{
      name: 'password',
      type: 'text',
      col: 8,
      value: ''
    }, {
      name: 'confirmPassword',
      type: 'textarea',
      col: 4,
      value: ''
    }]
  }],

And I set the values of the objects of the nested arrays like this:

updateField (name, value) {
  this.schema.forEach((formGroup, index) => {
    formGroup.fields.forEach(field => {
      if (field.name === name) field.value = value
    })
  })
},

Is there a way to avoid using two nested forEach? (Without using any library like Lodash?)

I have the following input:

 schema: [{
    fields: [{
      name: 'name',
      type: 'text',
      col: 10,
      value: ''
    }, {
      name: 'description',
      type: 'text',
      col: 2,
      value: ''
    }]
  }, {
    fields: [{
      name: 'password',
      type: 'text',
      col: 8,
      value: ''
    }, {
      name: 'confirmPassword',
      type: 'textarea',
      col: 4,
      value: ''
    }]
  }],

And I set the values of the objects of the nested arrays like this:

updateField (name, value) {
  this.schema.forEach((formGroup, index) => {
    formGroup.fields.forEach(field => {
      if (field.name === name) field.value = value
    })
  })
},

Is there a way to avoid using two nested forEach? (Without using any library like Lodash?)

Share Improve this question asked May 16, 2017 at 2:02 alexalex 7,61115 gold badges53 silver badges79 bronze badges 2
  • Yes, move the anonymous callback outside, declare a named function. – le_m Commented May 16, 2017 at 2:06
  • 1 Do you need the nested arrays? Seems to me if you changed your input format to have a single fields array it would be easier to work with. (If you can't change where it's ing from, can you change it before you start working with it?) – nnnnnn Commented May 16, 2017 at 2:09
Add a ment  | 

4 Answers 4

Reset to default 4

You can flatten your array using reduce and the spread operator to bine your arrays, then forEach over your flat array:

updateField (name, value) {
  this.schema
    .reduce((memo, item) => [...memo, ...item.fields], [])
    .forEach(field => {
      if (field.name === name) field.value = value;
    });
}

Sure but there isn't really a benefit to it.

Your current data structures are such that you are required to iterate over each subitem for each item in your array.

If only the appearance of nesting bothers you, you could separate the functions.

updateField (name, value) {
  const updateFormGroupField = field => {
     if (field.name === name) field.value = value;
  };

  const updateFormGroup = formGroup => formGroup.forEach(updateFormGroupField);

  this.schema.forEach(updateFormGroup)
}

That being said, there isn't really any benefit here other than personal flavor.

Perhaps a better focus would be to see how to reduce the quadratic plexity of these nested operations using a constant access structure like a Map or a Set

You can use for..of loop, object destructuring, Object.entries()

const obj = {
  schema: [{
    fields: [{
      name: 'name',
      type: 'text',
      col: 10,
      value: ''
    }, {
      name: 'description',
      type: 'text',
      col: 2,
      value: ''
    }]
  }, {
    fields: [{
      name: 'password',
      type: 'text',
      col: 8,
      value: ''
    }, {
      name: 'confirmPassword',
      type: 'textarea',
      col: 4,
      value: ''
    }]
  }],
  updateField(name, value) {
    for (let [key, {fields}] of Object.entries(this.schema)) {
      for (let [index, {name: _name}] of Object.entries(fields)) {
        if (name === _name) fields[index].value = value;
      }
    }
  }
}

obj.updateField("name", 123);

console.log(obj.schema[0].fields[0]);

I suggest introducing a generator function which facilitates iterating fields:

function* fields(schema) {
  for (let group of schema) yield* group.fields;
}

function updateField(name, value) {
  for (let field of fields(schema)) {
    if (field.name === name) field.value = value
  }
}

本文标签: javascriptHow to flatten a nested forEachStack Overflow