js 比较两个数组,并进行替换掉?

js 比较两个数组,并进行替换掉?

        let arr = [
          {
            sk: [
              { Name: '数据1', Value: '200' },
              { Name: '数据2', Value: '300' },
              { Name: '数据3', Value: '400' },
            ],
          },
          {
            sk: [
              { Name: '数据5', Value: '500' },
              { Name: '数据6', Value: '600' },
              { Name: '数据7', Value: '700' },
            ],
          },
        ];

        let arr2 = {
          name: '数据555',
          val: [200, 300, 500],
        };

需要根据arr2对象里面的val数组里面的值[200, 300, 500]去匹配arr1数组下sk数组里面的Value的值,如果arr1数组下sk数组里面的Value的值和arr2对象里面的val数组里面的值相等就替换Name,把arr2 对象的name 赋值到sk数组里面的Name

期望得到

        let arr = [
          {
            sk: [
              { Name: '数据555', Value: '200' },
              { Name: '数据555', Value: '300' },
              { Name: '数据3', Value: '400' },
            ],
          },
          {
            sk: [
              { Name: '数据555', Value: '200' },
              { Name: '数据555', Value: '500' },
              { Name: '数据7', Value: '700' },
            ],
          },
        ];
        let result = arr.map((item) => {
          if (item.sk.length == 0) return;
          item.sk.forEach((k) => {
            return {
              Name: arr2.val.find((t) => t == k.Value)?.name,
            };
          });
          return item;
        });

这样写了调试了还没效果。麻烦大佬们帮我看看

阅读 1.3k
avatarAI BotBETA

你的代码中存在一些问题,这可能是导致它没有按预期工作的原因。这里我提供了一种解决方案,使用了 Array.prototype.map()Array.prototype.find() 方法:

let arr = [
  {
    sk: [
      { Name: '数据1', Value: '200' },
      { Name: '数据2', Value: '300' },
      { Name: '数据3', Value: '400' },
    ],
  },
  {
    sk: [
      { Name: '数据5', Value: '500' },
      { Name: '数据6', Value: '600' },
      { Name: '数据7', Value: '700' },
    ],
  },
];

let arr2 = {
  name: '数据555',
  val: [200, 300, 500],
};

let result = arr.map((item) => {
  return item.sk.map((skItem) => {
    let found = arr2.val.find((v) => v == skItem.Value);
    if (found) {
      return { ...skItem, Name: arr2.name };
    } else {
      return skItem;
    }
  });
});

在这个代码中,我们首先遍历数组 arr 中的每个元素,然后对每个元素中的 sk 数组进行遍历。然后,我们使用 find() 方法在 arr2.val 数组中查找与当前 skItem.Value 相等的值。如果找到了匹配的值,我们将该 skItemarr2.name 合并并返回;否则,我们直接返回当前的 skItem

3 个回答
let result = arr.map((item) => {
    if (item.sk.length === 0) return;
    item.sk.forEach((k) => {
        if (arr2.val.includes(Number(k.Value))) {
            k.Name = arr2.name
        }
    });
    return item;
});

image.png

错有点多,注意序号,相同序号是对同一个错误的描述

// ❶ 这里有两层数组,对外层 map 替换掉的是第一层的对象
let result = arr.map((item) => {
    // ❸ 如果是 map,通常需要返回一个值/对象,
    // ❸ 直接 return 相当于 return undefined,
    // ❸ 也就是把 map 出来的新数组中对应位置的元素变成了 undefined
    if (item.sk.length == 0) return;
    // ❷ 对 item.sk 进行遍历处理,想法没错,但是处理错了
    // ❷ 需要适当改变 sk 中的元素,既然是改变,应该用 map,
    // ❷ 并且将 map 出来的新对象组成的数组赋值给 sk 替换掉它
    item.sk.forEach((k) => {
        return {
            // ❹ 新生成的对象只有 Name,没有 Value,至少应该补一个 Value 属性进去
            // ❺ arr2.val.find 找到的结果是 val 中的值,比如 200,它是没有 name 属性的,
            // ❺ 所以永远是 undefined
            Name: arr2.val.find((t) => t == k.Value)?.name,
        };
    });
    // ❶ 但是很显然,没有替换为新对象
    // ❶ 所以第一层是不需要 map 的,只需要 forEach 就好
    return item;
});

修改后的

// 因为原数据是字符串类型,所以将需要检索的数组值也改成字符串类型,
// 方便后面用 includes 来判断是否存在
const values = arr2.val.map(v => `${v}`);

// 直接遍历,在 arr 中修改对应的对象属性
arr.forEach(item => {
    if (!item.sk.length) { return; }

    // 注意 map 不会改变原数组,需要对 sk 重新赋值
    // 箭头函数返回一个对象的时候,可以用 ({...}),不需要 return
    item.sk = item.sk.map(k => ({
        // 判断如果值在事先准备的 values 中,用 arr2.name
        // 否则还是用 k.Name
        Name: values.includes(k.Value) ? arr2.name : k.Name,
        // 别忘了还有 Value
        Value: k.Value
    }));
});

因为是直接改原数据,所以里面的 map 其实也是可以用 forEach 遍历来处理的,直接替换掉符合条件的 Name 就行

const values = arr2.val.map(v => `${v}`);

arr.forEach(item => {
    if (!item.sk.length) { return; }

    item.sk.forEach(k => {
        // 遍历并对符合条件的数据替换掉 Name
        if (values.includes(k.Value)) {
            k.Name = arr2.name;
        }
    });
});

有2个知识点,

  1. 数组的 map 方法返回一个新数组,map参数中回调函数的返回值作为一个元素被添加为新数组中。
  2. 在 forEach 里面 return 实现的是类似 for 循环里 continue 语句的效果,return 的内容没什么作用。

你的需求要不要改动原数组?
改动原数组:

let arr2 = {
  name: '数据555',
  val: [200, 300, 500],
};

function change (arr) {
    arr.forEach(item => {
        if (item.sk) {
            item.sk = item.sk.map(skItem => {
                // 注意你提供的值,分别是 number 类型和 string 类型
                if (arr2.val.find(arr2Item => arr2Item.toString() === skItem.Value)) {
                    skItem.Name = arr2.name
                }
                return skItem
            })
        }
    })
}

change(arr);

不改动源数组:

let arr2 = {
  name: '数据555',
  val: [200, 300, 500],
};

function change (arr) {
    let result = arr.map(item => {
        if (item.sk) {
            item.sk = item.sk.map(skItem => {
                // 注意你提供的值,分别是 number 类型和 string 类型
                if (arr2.val.find(arr2Item => arr2Item.toString() === skItem.Value)) {
                    skItem.Name = arr2.name
                }
                return skItem
            })
        }
        return item;
    })
    return result;
}

change(arr);
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题