通过数组中的跟随位置向数组内的对象添加字段

时间:2017-09-26 06:07:46

标签: javascript arrays

我试图给数组中的对象一个关键,这将帮助我绘制它们之后,想法是数组是否包含2个(或更多)相同模型连续第一个对象得到type: 'first',最后得到type: 'last',它们之间会有什么type: 'between'但是如果它们之间还有其他模型,那么我就不要在里面推任何键。 让我们以此数组为例

const cars = [
  {
    id: 1,
    name: "z300",
    model: {
      id: 1,
      name: 'Suzuki'
    }
  },
  {
    id: 2,
    name: "swift 1",
    model: {
      id: 1,
      name: 'Suzuki'
    }
  },
  {
    id: 3,
    name: "swift 2",
    model: {
      id: 1,
      name: 'Suzuki'
    }
  },
  {
    id: 4,
    name: "i20",
    model: {
      id: 2,
      name: 'Hyundai'
    }
  },
  {
    id: 5,
    name: "swift 3",
    model: {
      id: 1,
      name: 'Suzuki'
    },
  },
  {
    id: 6,
    name: "superB",
    model: {
      id: 3,
      name: 'Skoda'
    }
  },
  {
    id: 7,
    name: "z300",
    model: {
      id: 1,
      name: 'Suzuki'
    }
  },
  {
    id: 8,
    name: "swift 30",
    model: {
      id: 1,
      name: 'Suzuki'
    }
  },
  {
    id: 9,
    name: "swift 31",
    model: {
      id: 1,
      name: 'Suzuki'
    }
  },
  {
    id: 10,
    name: "swift 32",
    model: {
      id: 1,
      name: 'Suzuki'
    }
  }
]

在这种情况下,我希望数组转换为

const cars = [
  {
    id: 1,
    name: "z300",
    model: {
      id: 1,
      name: 'Suzuki'
    },
    type: 'first'
  },
  {
    id: 2,
    name: "swift 1",
    model: {
      id: 1,
      name: 'Suzuki'
    },
    type: 'between'
  },
  {
    id: 3,
    name: "swift 2",
    model: {
      id: 1,
      name: 'Suzuki'
    },
    type: 'last'
  },
  {
    id: 4,
    name: "i20",
    model: {
      id: 2,
      name: 'Hyundai'
    }
  },
  {
    id: 5,
    name: "swift 3",
    model: {
      id: 1,
      name: 'Suzuki'
    },
  },
  {
    id: 6,
    name: "superB",
    model: {
      id: 3,
      name: 'Skoda'
    }
  },
  {
    id: 7,
    name: "z300",
    model: {
      id: 1,
      name: 'Suzuki'
    },
    type: 'first'
  },
  {
    id: 8,
    name: "swift 30",
    model: {
      id: 1,
      name: 'Suzuki'
    },
    type: 'between'
  },
  {
    id: 9,
    name: "swift 31",
    model: {
      id: 1,
      name: 'Suzuki'
    },
    type: 'between'
  },
  {
    id: 10,
    name: "swift 32",
    model: {
      id: 1,
      name: 'Suzuki'
    },
    type: 'last'
  }
]

如果数组中只有2个,我会将type: first添加到第一个,type: last添加到后者。 非常重要的是,我将保持数组的顺序(就好像同一个模型再次出现在单个对象中(在他之后没有相同的模态)他没有得到类型)但是这种情况可以是像同一个模型一样重复可以连续多次但在不同的位置找到。

现在我无法想到一个好方法,任何想法的方向都会受到欢迎:)

谢谢!

4 个答案:

答案 0 :(得分:2)

使用Array#reduce收集具有相同型号名称/ ID的一系列对象。然后再次使用reduce将对象转换为添加了类型的数组:

const cars = [{"id":1,"name":"z300","model":{"id":1,"name":"Suzuki"}},{"id":2,"name":"swift 1","model":{"id":1,"name":"Suzuki"}},{"id":3,"name":"swift 2","model":{"id":1,"name":"Suzuki"}},{"id":4,"name":"i20","model":{"id":2,"name":"Hyundai"}},{"id":5,"name":"swift 3","model":{"id":1,"name":"Suzuki"}},{"id":6,"name":"superB","model":{"id":3,"name":"Skoda"}},{"id":7,"name":"z300","model":{"id":1,"name":"Suzuki"}},{"id":8,"name":"swift 30","model":{"id":1,"name":"Suzuki"}},{"id":9,"name":"swift 31","model":{"id":1,"name":"Suzuki"}},{"id":10,"name":"swift 32","model":{"id":1,"name":"Suzuki"}}];

/** generate the the type according to the place in the series **/
const getType = (place, length) => 
  place === 0 ? 'first' : (place === length - 1 ? 'last' : 'between');

const result = cars
  /** reduce to an array of objects that describe a series of models **/ 
	.reduce((c, { model: { id } }, index) => {
		if(!index || id !== c[c.length - 1].id) { // if 1st or the current model name is not equal to the previous start a new series
			c.push({ id, carsIdx: [] }); // a series object
		}

		c[c.length - 1].carsIdx.push(index); // push the the current car index to the last series object

		return c;
	}, [])
  /** reduce the array of series back to an array of cars **/
	.reduce((r, { carsIdx }) => {
		if(carsIdx.length < 2) { // if the number of cars in the series is less than 2, just push the original object according to index
			carsIdx.forEach((idx) => r.push(cars[idx]));
		} else { // if not extend the car object with the type according to his place in the series
			carsIdx.forEach((idx, place, arr) => r.push(Object.assign({
				type: getType(place, arr.length)
			}, cars[idx])));
		}

		return r;
	}, []);

console.log(result);

答案 1 :(得分:2)

最直接且易于理解的解决方案之一是使用两个循环来查找每个模型序列的开始和结束(使用他们的模型ID)如下:

&#13;
&#13;
const cars = [
  { id: 1, name: "z300", model: {id: 1, name: 'Suzuki'} },
  { id: 2, name: "swift 1", model: {id: 1, name: 'Suzuki'} },
  { id: 3, name: "swift 2", model: {id: 1, name: 'Suzuki'} },
  { id: 4, name: "i20", model: {id: 2, name: 'Hyundai'} },
  { id: 5, name: "swift 3", model: {id: 1, name: 'Suzuki'} },
  { id: 6, name: "superB", model: {id: 3, name: 'Skoda'} },
  { id: 7, name: "z300", model: {id: 1, name: 'Suzuki'} },
  { id: 8, name: "swift 30", model: {id: 1, name: 'Suzuki'} },
  { id: 9, name: "swift 31", model: {id: 1, name: 'Suzuki'} },
  { id: 10, name: "swift 32", model: {id: 1, name: 'Suzuki'} }
];


var m, m1;
var n=cars.length;

for(var i=0; i<n; i++) {
    m = cars[i].model.id;
    if(m == m1) { //same model as prev item: new sequence detected
        cars[i-1].type = 'first';
        cars[i].type = 'between';
        for(i=i+1; i<n; i++) {
            m = cars[i].model.id;
            if (m != m1) break; //sequence finished
            cars[i].type = 'between';
        }
        cars[i-1].type = 'last';
    }
    m1 = m;
}

console.log(cars);
&#13;
&#13;
&#13;

答案 2 :(得分:0)

您可以使用循环来检查当前迭代数组中对象的上一个,当前值和下一个值

const cars = [{"id":1,"name":"z300","model":{"id":1,"name":"Suzuki"}},{"id":2,"name":"swift 1","model":{"id":1,"name":"Suzuki"}},{"id":3,"name":"swift 2","model":{"id":1,"name":"Suzuki"}},{"id":4,"name":"i20","model":{"id":2,"name":"Hyundai"}},{"id":5,"name":"swift 3","model":{"id":1,"name":"Suzuki"}},{"id":6,"name":"superB","model":{"id":3,"name":"Skoda"}},{"id":7,"name":"z300","model":{"id":1,"name":"Suzuki"}},{"id":8,"name":"swift 30","model":{"id":1,"name":"Suzuki"}},{"id":9,"name":"swift 31","model":{"id":1,"name":"Suzuki"}},{"id":10,"name":"swift 32","model":{"id":1,"name":"Suzuki"}}];

const [first, between, last] = ["first", "between", "last"];
for (let [key, car, index = +key] of Object.entries(cars)) {
  const {model: {name: _name}} = car; 
  if (index > 0) {
    let [prev, next] = [cars[index - 1], cars[index +1]];
    if (prev.model.name === _name) {
      if (next && next.model.name === _name 
        && !car.type && !prev.type) {
          [prev.type, car.type, next.type] = types;
       }
       if (prev.type === types[1] 
          && next && next.model.name === _name
          || next && next.model.name === _name) {
            car.type = between;
       }
       if (next && next.model.name !== _name 
          && prev.model.name === car.model.name 
          || !next && prev.model.name === _name) {
            car.type = last;
       }
    } 
  }
};

console.log(JSON.stringify(cars, null, 2));

答案 3 :(得分:-1)

在带有数组操作的纯javascript中存在一个简单的解决方案

for (var i = 0, l = cars.length; i < l; i++) {
    if(i==0)
   {if (cars[i]["model"]["name"]==cars[i+1]["model"]["name"])
      cars[i].model.type="first";}
    else if(i < cars.length-1)
    { if(cars[i]["model"]["name"]==cars[i+1]["model"]["name"] && cars[i]["model"]["name"]==cars[i-1]["model"]["name"])
     cars[i].model.type="between";
     else if(cars[i]["model"]["name"]!=cars[i+1]["model"]["name"] && cars[i]["model"]["name"]==cars[i-1]["model"]["name"] )
     cars[i].model.type="last";
     else if (cars[i]["model"]["name"]==cars[i+1]["model"]["name"])
      cars[i].model.type="first";
     }
     else
     {if(cars[i]["model"]["name"]==cars[i-1]["model"]["name"] )
     cars[i].model.type="last";}

}
console.log(cars);