【问题标题】:How to extend an object from another object based on values referred?如何根据引用的值从另一个对象扩展一个对象?
【发布时间】:2016-11-02 19:41:45
【问题描述】:

我有两个数组,每个元素都是一个对象:

var cars = [{
  brand: "VW",
  brand_id: "1",
  models: [
    {
      name: "Golf",
      model_id: "1"
    },
    {
      name: "Passat",
      model_id: "2"
    }
  ]
},
{
  brand: "BMW",
  brand_id: "2",
  models: [
    {
      name: "X3",
      model_id: "1"
    },
    {
      name: "X5",
      model_id: "2"
    }
  ]
}];

var drivers = [{
  name: "Test Driver",
  cars: [
    {
      brand_id: "1",
      model_id: "1"
    },
    {
      brand_id: "2",
      model_id: "1"
    }
  ]
}]

将模型名称复制到每个驾驶员的汽车对象中的最佳方法是什么?这是预期的结果:

var drivers = [{
  name: "Test",
  cars: [
    {
      brand_id: "1",
      model_id: "1",
      name: "Golf"
    },
    {
      brand_id: "2",
      model_id: "1",
      name: "X3"
    }
  ]
}]

我的想法是循环遍历驾驶员,然后循环遍历每个驾驶员的汽车,然后循环遍历每辆汽车,然后循环......这么多循环。我希望有更简单的方法来解决这个问题。

【问题讨论】:

    标签: javascript arrays object


    【解决方案1】:

    您可以使用两个forEach()loop 来执行此操作,循环驱动程序数组中的每个对象,然后循环当前对象内的汽车数组。之后,您可以使用两个find() 循环在汽车数组中查找具有相同brand_id 的对象,然后在模型内部查找具有相同model_id 的对象并返回name

    var cars = [{"brand":"VW","brand_id":"1","models":[{"name":"Golf","model_id":"1"},{"name":"Passat","model_id":"2"}]},{"brand":"BMW","brand_id":"2","models":[{"name":"X3","model_id":"1"},{"name":"X5","model_id":"2"}]}];
    var drivers = [{"name":"Test Driver","cars":[{"brand_id":"1","model_id":"1"},{"brand_id":"2","model_id":"1"}]}];
    
    drivers.forEach(function(e) {
      e.cars.forEach(function(c) {
        c.name = cars.find(function(a) {
          return a.brand_id == c.brand_id;
        }).models.find(function(a) {
          return c.model_id == a.model_id;
        }).name
      })
    })
    
    console.log(drivers)

    【讨论】:

      【解决方案2】:

      由于数据结构,您无法避免此处出现循环。但是你可以用一种相当干净的方式来做到这一点

      var cars = [{"brand":"VW","brand_id":"1","models":[{"name":"Golf","model_id":"1"},{"name":"Passat","model_id":"2"}]},{"brand":"BMW","brand_id":"2","models":[{"name":"X3","model_id":"1"},{"name":"X5","model_id":"2"}]}];
      var drivers = [{"name":"Test Driver","cars":[{"brand_id":"1","model_id":"1"},{"brand_id":"2","model_id":"1"}]}];
      
      drivers.forEach(expandCars);
      
      function expandCars(driver) {
        // map each car to list of car brands filtered by brand ID
        // then to resulting list of car models by model ID
        driver.cars = driver.cars.map(car => {
           var carModels = cars.filter(carBrand => carBrand.brand_id == car.brand_id)[0].models;
           var model = carModels.filter(carModel => carModel.model_id == car.model_id)[0];
          
           return Object.assign(car, model);
        });
      }
      
      
      
      console.log(drivers);

      老实说,这种数据结构看起来不必要地复杂。为什么cars是一个Brands列表,而每个Brand都有一个Models列表?为什么不让cars 数组看起来像driver.cars 数组,只是一个每个对象都有品牌和型号的平面列表?这将使搜索汽车的结构变得更加容易。 ModelID在品牌之间也应该是唯一的,所以你只需检查型号ID就知道如果型号相同则品牌必须相同。

      【讨论】:

      • 谢谢!数据结构实际上完全不同(在内容上),只是试图简化一个例子并使用汽车/品牌/模型。
      • 现在find 通常更可取,而不是使用filter 并获取结果的第一个元素。
      【解决方案3】:

      您可以对汽车使用哈希表,然后再分配名称。

      var cars = [{ brand: "VW", brand_id: "1", models: [{ name: "Golf", model_id: "1" }, { name: "Passat", model_id: "2" }] }, { brand: "BMW", brand_id: "2", models: [{ name: "X3", model_id: "1" }, { name: "X5", model_id: "2" }] }],
          drivers = [{ name: "Test Driver", cars: [{ brand_id: "1", model_id: "1" }, { brand_id: "2", model_id: "1" }] }],
          hash = Object.create(null);
      
      cars.forEach(function (brands) {
          brands.models.forEach(function (model) {
              hash[[brands.brand_id, model.model_id].join('|')] = model;
          });
      });
      
      drivers.forEach(function (driver) {
          driver.cars.forEach(function (car) {
              car.name = hash[[car.brand_id, car.model_id].join('|')].name;
          });
      });
      
      console.log(drivers);
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      【讨论】:

        【解决方案4】:

        使用Array.prototype.reduce 和哈希表的另一种解决方案 - 参见下面的演示:

        var cars=[{brand:"VW",brand_id:"1",models:[{name:"Golf",model_id:"1"},{name:"Passat",model_id:"2"}]},{brand:"BMW",brand_id:"2",models:[{name:"X3",model_id:"1"},{name:"X5",model_id:"2"}]}];
        var drivers=[{name:"Test Driver",cars:[{brand_id:"1",model_id:"1"},{brand_id:"2",model_id:"1"}]}];
        
        var result = drivers.reduce(function(hash) {
        
          // create a hash table first
          cars.forEach(function(element) {
            element.models.forEach(function(model) {
              hash[element.brand_id + "|" + model.model_id] = model.name;
            });
          });
        
          // now reduce it to obtain the result
          return function(prev, curr) {
            curr.cars.forEach(function(element) {
              element.name = hash[element.brand_id + "|" + element.model_id];
            });
            prev.push(curr);
            return prev;
          };
        }(Object.create(null)), []);
        
        console.log(result);
        .as-console-wrapper{top:0;max-height:100%!important;}

        【讨论】:

        • @passatgt 让我知道您对此的反馈,谢谢!
        【解决方案5】:
        drivers.cars.forEach(                                
          car =>                                             
            car.name =                                       
              cars.find(                                     
                car2 =>                                      
                  car2.brand_id === car.brand_id             
              )
                .models.find(                                
                  model => 
                    model.model_id === car.model_id
                ).name
        )
        

        英文:

        将drivers对象的cars列表中的每辆车的名称设置为首先在cars对象中查找具有正确品牌的汽车,然后在该汽车中找到model_id匹配的模型,并取它的名字。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-18
          • 2012-11-25
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-09-17
          相关资源
          最近更新 更多