es6合并两个对象数组并覆盖现有对象

时间:2017-11-29 14:06:09

标签: javascript arrays merge ecmascript-6

我有2个对象数组:

const arr1 = [{'id':'1' 'value':'yes'}, {'id':'2', 'value':'no'}];
const arr2 = [{'id':'2', 'value':'yes'}];

所以,如果我尝试合并这两个数组,结果应为:

arrTemp = [{'id':'1', 'value':'yes'}, {'id':'2', 'value':'yes'}];

基本上,它应该与Object.assign()类似,但无论我尝试什么它都不起作用。有人可以帮我吗?

我修改了数据结构。现在可以合并它们并获得输出。

由于

9 个答案:

答案 0 :(得分:4)

这是通过ES6传播,缩小和Object.values完成工作的方式。

const arr1 = [{
  'id': '1',
  'value': 'yes'
}, {
  'id': '2',
  'value': 'no'
}];
const arr2 = [{
  'id': '2',
  'value': 'yes'
}];

const result = Object.values([...arr1, ...arr2].reduce((result, {
  id,
  ...rest
}) => {
  result[id] = {
    ...(result[id] || {}),
    id,
    ...rest
  };
  return result;
}, {}));

console.log(result);

答案 1 :(得分:3)

intptr

您可以将数组(int *)传播到一个结果对象(通过const result = Object.entries(Object.assign({}, ...arr1,...arr2)).map(([key, value]) => ({[key]:value})); ),然后再将...条目传播到数组。

答案 2 :(得分:3)

您可以使用有效的ES6数据结构,例如地图:

const 1 = { 1: { string: 'yes' }, 2: { string: 'no' } } const 2 = { 2: { string: 'yes' }, 3: { string: 'no' } } const 3 = { ...1, ...2}

这将使用第二个参数覆盖您的第一个参数,或者只在可能的情况下组合它们。 只需在浏览器中试用它就可以轻松实现并提高性能,因为您永远不必使用findById()这是一项昂贵的操作。

答案 3 :(得分:2)

在javascript中,数组只是从0开始用数字索引的对象。

因此,当您在Object.assignarr1上使用arr2时,您将使用arr1中的第一项覆盖arr2中的第一项,因为它们是0两者都在密钥[ { '2': 'yes' }, { '2': 'no' } ] 下编制索引。

你的结果将是:

{ 
 0: { '2': 'yes' },
 1: { '2': 'no' }
}

(或在对象语法中:)

const arr1 = {
  '1': 'yes',
  '2': 'no'
};

const arr2 = {
  '2': 'yes'
};

const result = Object.assign(arr1, arr2);

您可以创建一个由数字字符串索引的对象,而不是使用数组(在任何情况下,您似乎都在想这个数组)。

因此,您可以更改原始数据结构,以简化工作:

using UnityEngine;
using System.Collections;

//Adding this allows us to access members of the UI namespace including Text.
using UnityEngine.UI;

public class CompletePlayerController : MonoBehaviour {

    public float speed;             //Floating point variable to store the player's movement speed.
    public Text countText;          //Store a reference to the UI Text component which will display the number of pickups collected.
    public Text winText;            //Store a reference to the UI Text component which will display the 'You win' message.

    private Rigidbody2D rb2d;       //Store a reference to the Rigidbody2D component required to use 2D Physics.
    private int count;              //Integer to store the number of pickups collected so far.

    public GameObject bulletPrefab;

    public Transform bulletSpawn;

    // Use this for initialization
    void Start()
    {
        //Get and store a reference to the Rigidbody2D component so that we can access it.
        rb2d = GetComponent<Rigidbody2D> ();

        //Initialize count to zero.
        count = 0;

        //Initialze winText to a blank string since we haven't won yet at beginning.
        winText.text = "";

        //Call our SetCountText function which will update the text with the current value for count.
        SetCountText ();
    }

    //FixedUpdate is called at a fixed interval and is independent of frame rate. Put physics code here.
    void FixedUpdate()
    {
        //Store the current horizontal input in the float moveHorizontal.
        float moveHorizontal = Input.GetAxis ("Horizontal");

        //Store the current vertical input in the float moveVertical.
        float moveVertical = Input.GetAxis ("Vertical");

        //Use the two store floats to create a new Vector2 variable movement.
        Vector2 movement = new Vector2 (moveHorizontal, moveVertical);

        //Call the AddForce function of our Rigidbody2D rb2d supplying movement multiplied by speed to move our player.
        rb2d.AddForce (movement * speed);

        if (!isLocalPlayer)
        {
            return;
        }

        var x = Input.GetAxis("Horizontal") * Time.deltaTime * 150.0f;
        var z = Input.GetAxis("Vertical") * Time.deltaTime * 3.0f;

        transform.Rotate(0, x, 0);
        transform.Translate(0, 0, z);

        if (Input.GetKeyDown(KeyCode.Space))
        {
            Fire();
        }


    }

    void Fire()
    {
    // Create the Bullet from the Bullet Prefab
        var bullet = (GameObject)Instantiate (
        bulletPrefab,
        bulletSpawn.position,
        bulletSpawn.rotation);

    // Add velocity to the bullet
        bullet.GetComponent<Rigidbody>().velocity = bullet.transform.forward * 6;

    // Destroy the bullet after 2 seconds
        Destroy(bullet, 2.0f);
    }

     public override void OnStartLocalPlayer ()
    {
        GetComponent<MeshRenderer>().material.color = Color.blue;
    }


    //OnTriggerEnter2D is called whenever this object overlaps with a trigger collider.
    void OnTriggerEnter2D(Collider2D other) 
    {
        //Check the provided Collider2D parameter other to see if it is tagged "PickUp", if it is...
        if (other.gameObject.CompareTag ("PickUp")) 
        {
            //... then set the other object we just collided with to inactive.
            other.gameObject.SetActive(false);

            transform.localScale += new Vector3(0.1f, 0.1f, 0);

            //Add one to the current value of our count variable.
            count = count + 1;

            //Update the currently displayed count by calling the SetCountText function.
            SetCountText ();
        }


    }

    //This function updates the text displaying the number of objects we've collected and displays our victory message if we've collected all of them.
    void SetCountText()
    {
        //Set the text property of our our countText object to "Count: " followed by the number stored in our count variable.
        countText.text = "Count: " + count.ToString ();

        //Check if we've collected all 12 pickups. If we have...
        if (count >= 12)
            //... then set the text property of our winText object to "You win!"
            winText.text = "You win!";
    }
}

答案 4 :(得分:0)

您不能使用array.prototype映射,因为arr1和arr2的键具有相同的值'2'。

你应该使用这样的东西

for (var i = 0, l = arr1.length; i < l; i++) {
 var key = Object.keys(arr1[i]);
 if (!arr2[key]) { arr2[key] = []; }
 arr2[key].push(arr1[i][key]);
}

问候

答案 5 :(得分:0)

您可以将Map作为对结果数组中新分配对象的引用,并首先构建一个包含对象副本的新数组,然后迭代第二个数组并使用相同的键更新对象。

&#13;
&#13;
var array1 = [{ 1: 'yes' }, { 2: 'no' }],
    array2 = [{ 2: 'yes' }],
    getKey = o => Object.keys(o)[0],
    map = new Map,
    result = array1.map(o => (k => map.set(k, Object.assign({}, o)).get(k))(getKey(o)));

array2.forEach(o => Object.assign(map.get(getKey(o)), o));

console.log(result);
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
&#13;
&#13;

答案 6 :(得分:0)

使用对象的存在数组添加的简单方法:

const arr1 = [{ "name":"John", "age":30, "car":"toyata" }];
const arr2 = [{ "name":"Ales", "age":40, "car":"Nissan" }];
Array.prototype.push.apply(arr1, arr2);

Result:=>
console.log(arr1)

答案 7 :(得分:0)

对于以后找到此答案的任何人。您可以通过两种方法使其正常工作,但是可以过滤第一个数组中所有调整后的元素,然后将其与第二个数组组合。

const arr3 = [...arr1.filter(item1 => !arr2.find(item2 => item1.id === item2.id)), ...arr2]

或者,您可以更新第一个数组中的元素,然后从第二个数组中过滤它们。

答案 8 :(得分:0)

Array reduce 在这种情况下可以派上用场。请参见下面的示例:

[...arr1, ...arr2].reduce((acc, item) => {
  const updated = acc.find(a => a.id === item.id)
  if (!updated) {
    acc.push(item)
  } else {
    const index = acc.indexOf(updated)
    acc[index] = { ...item, ...acc[index] }
  }
  return acc
}, [])