【问题标题】:Angular / typescript two dimensional array problemAngular / typescript二维数组问题
【发布时间】:2019-09-24 01:24:14
【问题描述】:

我正在通过重新使用以前设置的对象(Angular/Typescript)对 2 个暗淡对象数组进行分配。我的结果显示最后一个分配覆盖了前两个,我不知道为什么。你能看看我错过了什么吗?

    export interface Criteria {
        fieldValue: any;
        fieldName: string;
        childItems?: Criteria[];
    }


                        // function to build my array of objects:
    setCriteria() {
                       // parent object 1 
                       // to be reused / reassigned to array below
    const criteriaLevel1: Criteria = {
      fieldName: 'Criteria name',
      fieldValue: 'Crit-Level-1',
      childItems: []
    };
                       // parent object 2 - child of  object 1
                       // to be reused / reassigned to array below
                       // into - childItems[0]
    const criteriaLevel2: Criteria = {
      fieldName: 'Criteria name',
      fieldValue: 'Crit-Level-2',
      childItems: []
    };
                       // list of 3 different items to be assigned to array 
                       // into - childItems[0].childItems[0] of each array record.
    const itemsABC: string[] = [
      'item AAA',
      'item BBB',
      'item CCC'
    ];

    const criteriaArray = [];
    let ix = 0;

    itemsABC.forEach(item => {

      console.log('item: ' + item);

      criteriaArray[ix] = [];
      criteriaArray[ix][0] = criteriaLevel1;
      criteriaArray[ix][0].childItems[0] = criteriaLevel2;
      criteriaArray[ix][0].childItems[0].childItems[0] = {
          fieldName: 'name',
          fieldValue: item + '-' + ix
      };
      ix++;
    });

    // output test

    for (let i = 0; i < 3; i++) {
      console.log('ix: ' + i);
      for (const itemA of criteriaArray[i]) {
        console.log('a: ' + itemA.fieldName + ' - ' + itemA.fieldValue);
        for (const itemB of itemA.childItems) {
          console.log('b: ' + itemB.fieldName + ' - ' + itemB.fieldValue);
          for (const itemC of itemB.childItems) {
            console.log('c: ' + itemC.fieldName + ' - ' + itemC.fieldValue);
          }
        }
      }

    }
  }

我得到这个输出:

索引:0 - 插入项目:项目 AAA

索引:1 - 插入项目:项目 BBB

索引:2 - 插入项目:项目 CCC

ix: 0

a:条件名称 - Crit-Level-1

b:条件名称 - Crit-Level-2

c: name - item CCC-2 // 但我在这里期待:item AAA-0

ix: 1

a:条件名称 - Crit-Level-1

b:条件名称 - Crit-Level-2

c: name - item CCC-2 // 但我在这里期待:item BBB-1

ix: 2

a:条件名称 - Crit-Level-1

b:条件名称 - Crit-Level-2

c: name - item CCC-2 // 是,正如预期的那样:item CCC-2

我做错了什么?

【问题讨论】:

    标签: javascript arrays angular typescript


    【解决方案1】:

    您正在分配对对象的引用,因此criteriaArray 的所有三个元素都指向criteriaLevel1criteriaLevel2 的相同实例


    您有几个选择来保持相同的模式:

    Spread syntax(但请注意the compatibility matrix

    criteriaArray[ix][0] = {...criteriaLevel1, childItems: []};
    criteriaArray[ix][0].childItems[0] = {...criteriaLevel2, childItems: []};
    

    const criteriaLevel1 = {
      fieldName: 'Criteria name',
      fieldValue: 'Crit-Level-1',
      childItems: []
    };
    
    const criteriaLevel2 = {
      fieldName: 'Criteria name',
      fieldValue: 'Crit-Level-2',
      childItems: []
    };
      
    const itemsABC = [
      'item AAA',
      'item BBB',
      'item CCC'
    ];
    
    const criteriaArray = [];
    let ix = 0;
    
    itemsABC.forEach(item => {
      console.log('item: ' + item);
    
      criteriaArray[ix] = [];
      criteriaArray[ix][0] = {...criteriaLevel1, childItems: []};
      criteriaArray[ix][0].childItems[0] = {...criteriaLevel2, childItems: []};
      criteriaArray[ix][0].childItems[0].childItems[0] = {
        fieldName: 'name',
        fieldValue: item + '-' + ix
      };
        ix++;
    });
    
    for (let i = 0; i < 3; i++) {
      console.log('ix: ' + i);
      for (const itemA of criteriaArray[i]) {
        console.log('a: ' + itemA.fieldName + ' - ' + itemA.fieldValue);
        for (const itemB of itemA.childItems) {
          console.log('b: ' + itemB.fieldName + ' - ' + itemB.fieldValue);
          for (const itemC of itemB.childItems) {
            console.log('c: ' + itemC.fieldName + ' - ' + itemC.fieldValue);
          }
        }
      }
    }

    Object.assign()

    criteriaArray[ix][0] = Object.assign({}, criteriaLevel1, {childItems: []});
    criteriaArray[ix][0].childItems[0] = Object.assign({}, criteriaLevel2, {childItems: []});
    

    const criteriaLevel1 = {
      fieldName: 'Criteria name',
      fieldValue: 'Crit-Level-1',
      childItems: []
    };
    
    const criteriaLevel2 = {
      fieldName: 'Criteria name',
      fieldValue: 'Crit-Level-2',
      childItems: []
    };
      
    const itemsABC = [
      'item AAA',
      'item BBB',
      'item CCC'
    ];
    
    const criteriaArray = [];
    let ix = 0;
    
    itemsABC.forEach(item => {
      console.log('item: ' + item);
    
      criteriaArray[ix] = [];
      criteriaArray[ix][0] = Object.assign({}, criteriaLevel1, {childItems: []});
      criteriaArray[ix][0].childItems[0] = Object.assign({}, criteriaLevel2, {childItems: []});
      criteriaArray[ix][0].childItems[0].childItems[0] = {
        fieldName: 'name',
        fieldValue: item + '-' + ix
      };
        ix++;
    });
    
    for (let i = 0; i < 3; i++) {
      console.log('ix: ' + i);
      for (const itemA of criteriaArray[i]) {
        console.log('a: ' + itemA.fieldName + ' - ' + itemA.fieldValue);
        for (const itemB of itemA.childItems) {
          console.log('b: ' + itemB.fieldName + ' - ' + itemB.fieldValue);
          for (const itemC of itemB.childItems) {
            console.log('c: ' + itemC.fieldName + ' - ' + itemC.fieldValue);
          }
        }
      }
    }

    请注意,这两种方法都执行浅拷贝,因此您必须手动考虑嵌套对象引用。


    另一种方法是创建一个辅助函数来实例化一个新对象。

    function generateCriteria(fieldName, fieldValue) {
      return () => ({
        fieldName: fieldName,
        fieldValue: fieldValue,
        childItems: []
      });
    }
    
    const criteriaLevel1 = generateCriteria('Criteria name', 'Crit-Level-1');
    const criteriaLevel2 = generateCriteria('Criteria name', 'Crit-Level-2');
    
    const itemsABC = [
      'item AAA',
      'item BBB',
      'item CCC'
    ];
    
    const criteriaArray = [];
    let ix = 0;
    
    itemsABC.forEach(item => {
      console.log('item: ' + item);
    
      criteriaArray[ix] = [];
      criteriaArray[ix][0] = criteriaLevel1();
      criteriaArray[ix][0].childItems[0] = criteriaLevel2();
      criteriaArray[ix][0].childItems[0].childItems[0] = {
        fieldName: 'name',
        fieldValue: item + '-' + ix
      };
        ix++;
    });
    
    for (let i = 0; i < 3; i++) {
      console.log('ix: ' + i);
      for (const itemA of criteriaArray[i]) {
        console.log('a: ' + itemA.fieldName + ' - ' + itemA.fieldValue);
        for (const itemB of itemA.childItems) {
          console.log('b: ' + itemB.fieldName + ' - ' + itemB.fieldValue);
          for (const itemC of itemB.childItems) {
            console.log('c: ' + itemC.fieldName + ' - ' + itemC.fieldValue);
          }
        }
      }
    }

    【讨论】:

      【解决方案2】:

      按值对象和按引用对象是一件棘手的事情。当您在第 1 次迭代中分配 criterialLevel1 时,在下一次迭代中,您实际上一直在更新 criteriaLeve1 变量的引用。

      criteriaArray[ix] = [];
      criteriaArray[ix][0] = {...criteriaLevel1, childItems: []}; // creating a new object and spreading it, Note the child Items created new else as it is an array would have been passed by reference as well.
      criteriaArray[ix][0].childItems[0] = {...criteriaLevel2, childItems: []};
      criteriaArray[ix][0].childItems[0].childItems[0] = {
        fieldName: 'name',
        fieldValue: item + '-' + ix
      };
      

      我建议宁可定义这些变量,为什么不直接分配它们,您可以在一行中完成:

      criteriaArray[ix] = [{
        fieldName: 'Criteria name', 
        fieldValue: 'Crit-Level-1', 
        childItems: [{
          fieldName: 'Criteria name', 
          fieldValue: 'Crit-Level-2', 
          childItems: [{
            fieldName: 'name',
            fieldValue: item + '-' + ix
          }]
        }] 
      }];
      

      【讨论】:

      • 谢谢。这将是一个解决方案,但由于可能涉及更长的列表和更多的父子级别,因此需要另一种方法。
      • 签出第一个传播对象并用它创建新的对象
      猜你喜欢
      • 2012-09-13
      • 2019-08-08
      • 2011-04-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-10
      • 2010-12-15
      • 1970-01-01
      相关资源
      最近更新 更多