likes
comments
collection
share

数组常用操作

作者站长头像
站长
· 阅读数 55

1. 数组的合并与拆分

  • concat() 方法合并两个数组
let arr3 = [1, 2, 3, 4];
let arr4 = ['a', 'b', 'c'];
let res = arr3.concat(arr4); // [1, 2, 3, 4, "a", "b", "c"]

[0].concat(...[1, 2])  //[0, 1, 2]
  • slice() 方法可从已有的数组中返回选定的元素

    arr.slice(a, b) 返回一个新的数组,包含从 a 到 b(不包括该元素)的元素。

let arr = [1, 2, 3, 4, 5];
let res = arr.slice(1, 3);   // [2, 3]

let arr = [1, 2, 3, 4, 5];
let res = arr.slice(1); // [2, 3, 4, 5]

2.树形结构转换为扁平数组

var tree = [
  {
    "id":10,
    "pid":"-1",
    "children":[
      {"id":11,"pid":"1","children":[]},
      {"id":12,"pid":"1","children":[]}
    ]
  }
];
//方法一:扁平化,但是未去除children属性
function flatten (arr) {
  return [].concat(...arr.map(item => [].concat(item, ...flatten(item.children))))
}

flatten(tree) 
//[
//  {"id":10,"pid":"-1",,"children":[{"id":11,"pid":"1","children":[]},{"id":12,"pid":"1","children":[]}]},
//  {"id":11,"pid":"1","children":[]},
//  {"id":12,"pid":"1","children":[]}
//]

//方法二:扁平化,并且去除children属性
function treeToList(tree) {
  var queen = [];
  var out = [];
  queen = queen.concat(tree);
  while(queen.length) {
    var first = queen.shift();
    if (first.children) {
      queen = queen.concat(first.children)
      delete first['children'];
    }

    out.push(first);
  }
  return out;
}

treeToList(tree) 
//[
//  {"id":10,"pid":"-1"},
//  {"id":11,"pid":"1"},
//  {"id":12,"pid":"1"}
//]

3.扁平数组转换为树形结构

let arr = [
  {id: 10, pid: '0'},
  {id: 11, pid: '1'},
  {id: 12, pid: '1'}
]

let newArr1 = [
  {
    "id":10,
    "pid":"0",
    "children":[
      {"id":11,"pid":"1","children":[]},
      {"id":12,"pid":"1","children":[]}
    ]
  }
]
let newArr2 = [
  {
    "id":10,
    "pid":"0",
    "children":[
      {"id":11,"pid":"1","children":[],"level":1},
      {"id":12,"pid":"1","children":[],"level":1}
    ],
   "level":0
   }
]

//将arr转换成newArr1
function listToTree(list) {
  var map = {}, node, tree= [], i;
  for (i = 0; i < list.length; i ++) {
    map[list[i].id] = list[i]; 
    list[i].children = []; 
  }
  for (i = 0; i < list.length; i += 1) {
    node = list[i];
    if (node.pid !== '0') {
      map[node.pid].children.push(node);
    } else {
      tree.push(node);
    }
  }
  return tree;
}

listToTree(arr); 

//将arr转换成newArr2
function listToTreeWithLevel(list, parent, level) {
  var out = []
  for (var node of list) {  
    if (node.pid == parent) {
      node.level = level;
      var children = listToTreeWithLevel(list, node.id, level + 1)
      if (children.length) {
        node.children = children
      }
      out.push(node)
    }
  }
  return out
}

listToTreeWithLevel(arr, '-1', 0)

4.数组降维,扁平化处理

const arr = [[1, 2, 3], [4, 5, 6]];
[].concat.apply([], arr);  //[1, 2, 3, 4, 5, 6];

//从list1变成list2
let list1 = [
  { a: [{ id: 1, name: "jack" }, { id: 2, name: "bob" }] },
  { a: [{ id: 3, name: "mary" }, { id: 4, name: "tom" }] }
];

let list2 = [
  { id: 1, name: "jack" },
  { id: 2, name: "bob" },
  { id: 3, name: "mary" },
  { id: 4, name: "tom" }
];

let list = list1.map(item => {
  return item.a.map(sub => {
    return {
      id: sub.id,
      name: sub.name
    };
  });
});

let arr = [].concat.apply([],list)
//let arr = [].concat(...list)
//let arr = list.flat() // 存在浏览器兼容问题

5.过滤已选择的项

// availableList: 包含所有可用项的数组
// selectedList: 包含已经选择的项的数组
this.list = this.availableList.filter(item => {
  return selectedList.findIndex(chose => {
    return chose.id === item.id;
  }) <= -1;
});

6.数组去重

6.1. 普通数组

  • 利用 Set 数据结构去重

    将数组转化为 SetSet 自动去除重复的元素,然后再将 Set 转化回数组即可。

const arr = [1, 2, 3, 3, 4, 4, 5];
const uniqueArr = [...new Set(arr)];
console.log(uniqueArr); // [1, 2, 3, 4, 5]
  • 利用 reduce() 方法去重

    使用 reduce() 方法遍历数组,利用一个空数组存储不重复的元素,每次将不重复的元素 push 到数组中。

const arr = [1, 2, 3, 3, 4, 4, 5];
const uniqueArr = arr.reduce((acc, cur) => {
    if (!acc.includes(cur)) {
        acc.push(cur);
    }
    return acc;
}, []);
console.log(uniqueArr); // [1, 2, 3, 4, 5]
  • 利用 filter() 方法去重

    使用 filter() 方法遍历数组,利用 indexOf() 方法判断元素是否在数组中第一次出现的位置,将第一次出现的元素保留下来。

const arr = [1, 2, 3, 3, 4, 4, 5];
const uniqueArr = arr.filter((item, index, arr) => {
    return arr.indexOf(item) === index;
});
console.log(uniqueArr); // [1, 2, 3, 4, 5]

6.2. 对象数组

  • 🌰 假设有一个对象数组,需要根据 name 属性进行去重操作:
const arr = [
  { name: "apple", value: 1 },
  { name: "banana", value: 2 },
  { name: "orange", value: 3 },
  { name: "apple", value: 4 },
  { name: "orange", value: 5 },
];
  • 使用 reduce() 方法去重
const uniqueArr = arr.reduce((acc, cur) => {
  const index = acc.findIndex((item) => item.name === cur.name);
  if (index === -1) {
    acc.push(cur);
  } else {
    acc[index] = cur;
  }
  return acc;
}, []);

console.log(uniqueArr);
// Output: [
//   { name: "apple", value: 4 },
//   { name: "banana", value: 2 },
//   { name: "orange", value: 5 }
// ]
  • 使用 Map 数据结构去重
const map = new Map();
arr.forEach((item) => {
  map.set(item.name, item);
});

const uniqueArr = [...map.values()];

console.log(uniqueArr);
// Output: [
//   { name: "apple", value: 4 },
//   { name: "banana", value: 2 },
//   { name: "orange", value: 5 }
// ]
  • 使用 filter() 方法去重
const uniqueArr = arr.filter(
  (item, index, arr) =>
    arr.findIndex((t) => t.name === item.name) === index
);

console.log(uniqueArr);
// Output: [
//   { name: "apple", value: 1 },
//   { name: "banana", value: 2 },
//   { name: "orange", value: 3 }
// ]
  • lodash 库的 uniqBy 方法

    如果你的项目中已经使用了 lodash 库,并且有需要按照某个属性或条件去重数组,那么使用 uniqBy 方法是一个不错的选择。这个方法接受一个数组和一个用于确定唯一性的属性或条件的函数。

import { uniqBy } from 'lodash';

let uniqueArray = uniqBy(arr, 'name');
console.log(uniqueArray);
//[
//   { name: "apple", value: 1 },
  // { name: "banana", value: 2 },
  // { name: "orange", value: 3 }
// ];

在这个例子中,uniqBy 方法使用对象数组和属性 'id',以确保根据 'id' 属性的唯一性进行去重。你可以根据实际需求修改属性或条件。这种方法对于复杂对象数组的去重非常方便。

6.3.不同类型的元素的数组

const arr = [1, 1, '2', 3, 1, 2,
    { name: '张三', id: { n: 1 }},
    { name: '张三', id: { n: 1 }},
    { name: '张三', id: { n: 2 }}
]

function uniqueArray(arr) {
    // 创建一个空数组,用于存放去重后的结果
    const unique = [];
    // 创建一个Map对象,用于记录已经遇到的元素
    const map = new Map();

    // 遍历输入的数组
    for (const item of arr) {
        let key;
      
        // 检查item的类型
        if (typeof item === 'object') {
            // 如果item是一个对象,将其转换为字符串形式
            // 注意:这假设对象属性顺序是固定的
            key = JSON.stringify(item);
        } else {
            // 如果item是原始值(如数字或字符串),直接使用它作为键
            key = item;
        }

        // 检查Map中是否已经有了这个键
        if (!map.has(key)) {
            // 如果没有,将这个键添加到Map中
            map.set(key, true);
            // 同时将这个唯一的项添加到结果数组中
            unique.push(item);
        }
    }
    return unique;
}

uniqueArray(arr);
// 输出: 
// [1, "2", 3, 2, 
//   { name: '张三', id: { n: 1 }}, 
//   { name: '张三', id: { n: 2 }}
// ]

7.多维数组去重

  • 使用ES6的new Set()实现去重

    使用数组的 flat 方法将多维数组降维为一维数组,参数 Infinity 表示不论多少维,都要将数组降维为一维。然后使用 ES6 的扩展运算符将 Set 转换为数组,并返回去重后的数组。

⚠️需要注意的是,使用 flat 方法可能会对一些较老的浏览器不兼容。

//兼容性不太好的写法:
function uniqueArr(arr) {
  return [...new Set(arr.flat(Infinity))]
}

const arr = [1, [2, 3], [2, 3], [4, 5], [4, 5], 1];
uniqueArr(arr); // 输出: [1, 2, 3, 4, 5]
  • 递归方法

    适用于任意多维数组,不受数据类型限制。同时,递归方法可以边遍历边去重,减少了内存占用。

function uniqueArr(arr) {
  let result = [];
  let obj = {};
  for (let i = 0; i < arr.length; i++) {
    let item = arr[i];
    if (Array.isArray(item)) {
      item = uniqueArr(item);
    }
    if (!obj[item]) {
      result.push(item);
      obj[item] = true;
    }
  }
  return result;
}

const arr = [1, [2, 3], [2, 3], [4, 5], [4, 5], 1];
uniqueArr(arr); // 输出: [[1, [2, 3], [4, 5]]
// 降维去重:
function uniqueArr(arr) {
  let result = [];
  let obj = {};

  for (let i = 0; i < arr.length; i++) {
    let item = arr[i];
    if (Array.isArray(item)) {
      item = uniqueArr(item);
    }

    // 如果是数组,将其扁平化并去除重复元素
    if (Array.isArray(item)) {
      for (let j = 0; j < item.length; j++) {
        let subItem = item[j];
        if (!obj[subItem]) {
          result.push(subItem);
          obj[subItem] = true;
        }
      }
    } else {
      // 如果是基本类型,直接去除重复
      if (!obj[item]) {
        result.push(item);
        obj[item] = true;
      }
    }
  }

  return result;
}

const arr = [1, [2, 3], [2, 3], [4, 5], [4, 5], 1];
uniqueArr(arr); // 输出: [1, 2, 3, 4, 5]
  • 将多维数组降维后再去重

    适用于需要对大规模数据进行去重操作的场景,因为可以利用 Set 数据结构去除数组中的重复项,从而提高去重效率。但是,这种方法需要将多维数组降维为一维数组,会占用更多的内存

// 将数组降维
function resetArray(arr, newArr){
  arr.forEach(item => {
    if (toString.call(item) === "[object Array]") {
      resetArray(item, newArr);
    } else {
      newArr.push(item);
    }
  })
}

// 将数组去重
function uniqueArr(arr) {
  var newArr = [];
  resetArray(arr, newArr);
  console.log([...new Set(newArr)]);
}

const arr = [1, [2, 3], [2, 3], [4, 5], [4, 5], 1];
uniqueArr(arr); // 输出: [1, 2, 3, 4, 5]

8.求数组对象的交集

const arr1 = [
  { name: 'name1', id: 1 },
  { name: 'name2', id: 2 },
  { name: 'name3', id: 3 }
];
const arr2 = [
  { name: 'name1', id: 1 },
  { name: 'name4', id: 4 },
  { name: 'name5', id: 5 }
];

const res = arr1.filter(item => arr2.findIndex(chose => chose.id === item.id) > -1)
// 输出: [
//   { name: 'name1', id: 1 }
// ]

9.求数组对象的并集

const arr1 = [
  { name: 'name1', id: 1 },
  { name: 'name2', id: 2 },
  { name: 'name3', id: 3 }
];
const arr2 = [
  { name: 'name1', id: 1 },
  { name: 'name4', id: 4 },
  { name: 'name5', id: 5 }
];

// 两个数组合并,并去重
// 方法一:
const res1 = arr1.concat(arr2.filter(item => arr1.findIndex(chose => chose.id == item.id) == -1))

// 方法二:
const obj = [];
const res2 = arr1.concat(arr2).reduce(function (prev, cur, index, arr) {
  obj[cur.id] ? '' : obj[cur.id] = true && prev.push(cur);
  return prev;
}, []);

// 输出: [
//   { name: 'name1', id: 1 },
//   { name: 'name2', id: 2 },
//   { name: 'name3', id: 3 },
//   { name: 'name4', id: 4 },
//   { name: 'name5', id: 5 }
// ]

10.求数组对象的差集

const arr1 = [
  { name: 'name1', id: 1 },
  { name: 'name2', id: 2 },
  { name: 'name3', id: 3 }
];
const arr2 = [
  { name: 'name1', id: 1 },
  { name: 'name4', id: 4 },
  { name: 'name5', id: 5 }
];
// 取差集  arr1相对于arr2所没有的
const res1 = arr1.filter(item1 => !arr2.find(item2 => item1.id == item2.id))
// 或者使用 some: 
// const res1 = arr1.filter(item1 => !arr2.some(item2 => item1.id === item2.id));
// 输出:[
//   { name: 'name2', id: 2 },
//   { name: 'name3', id: 3 }
// ]

// 取差集  arrB相对于arrA所没有的
const res2 = arr2.filter(item2 => !arr1.find(item1 => item1.id == item2.id))
// 输出:[
//   { name: 'name4', id: 4 },
//   { name: 'name5', id: 5 }
// ]

11.树数据字段映射

  • 使用场景:数据格式是树形层级的 但字段对应属性不是想要的
// data 原始树形数据
// map 字段映射对象 例子:{value: 'code', label: 'name', children: 'child'}
treeDataMapping (data, map) {
  const result = [];
  // 遍历 tree
  data.forEach(item => {
    // 读取 map 的键值映射
    const value = item[map.value];
    const label = item[map.label];
    let children = item[map.children];
    // 如果有子节点,递归
    if ( children ) {
      children = this.treeDataMapping(children, map);
    }
    result.push({
      value,
      label,
      children
    });
  });
  return result;
}
// 举例
const originalTreeData = [
  {
    id: 1,
    name: "节点1",
    code: "A01",
    child: [
      {
        id: 2,
        name: "子节点1.1",
        code: "A01-1",
        child: [
          {
            id: 4,
            name: "子节点1.1.1",
            code: "A01-1-1",
          },
        ],
      },
      {
        id: 3,
        name: "子节点1.2",
        code: "A01-2",
      },
    ],
  },
  {
    id: 5,
    name: "节点2",
    code: "A02",
  },
];

const fieldMap = {
  value: 'code',
  label: 'name',
  children: 'child',
};

treeDataMapping (originalTreeData, fieldMap)
// 输出: [
//   {
//     value: 'A01',
//     label: '节点1',
//     children: [
//       {
//         value: 'A01-1',
//         label: '子节点1.1',
//         children: [
//           {
//             value: 'A01-1-1',
//             label: '子节点1.1.1',
//             children: []
//           }
//         ]
//       },
//       {
//         value: 'A01-2',
//         label: '子节点1.2',
//         children: []
//       }
//     ]
//   },
//   {
//     value: 'A02',
//     label: '节点2',
//     children: []
//   }
// ]

12.查找一个节点的所有父节点

  • 查找一个节点的所有父节点(返回的数据包含本身)
// array 原始树形数据
// id 子节点id
familyTree (array, id) {
  let result = [];
  let flat = true;

  let forFn = (arr, value) => {
    arr.forEach(item => {
      if ( !flat ) return;
      result.push(item['value']);
      if ( item['value'] === value ) {
        flat = false;
      } else if ( item['children'] ) {
        forFn(item['children'], value);
      } else {
        result.pop();
      }
    });
    if ( flat ) result.pop();
  };

  forFn(array, id);

  return result;
}
// 举例
const familyTreeArray = [
  {
    value: 'Grandfather',
    children: [
      {
        value: 'Father',
        children: [
          { value: 'Me', children: [] },
          { value: 'Brother', children: [] }
        ]
      },
      {
        value: 'Uncle',
        children: [
          { value: 'Cousin', children: [] }
        ]
      }
    ]
  },
  {
    value: 'Great Grandfather',
    children: []
  }
];

familyTree(familyTreeArray, 'Me')
// ['Grandfather', 'Father', 'Me']

13.写一个获取数组的最大值、最小值的方法

  • 使用 Math.max.apply() Math.min.apply() 方法来获取数组中的最大值和最小值。

  • 这两个方法都需要传递一个数组作为第二个参数,其中数组的元素将作为 Math.max()Math.min() 方法的参数。由于 Math.max()Math.min() 方法不能直接接受数组作为参数,因此我们需要使用 Function.prototype.apply() 方法将数组元素作为单独的参数传递给这两个方法。

var arr1 = [25,62,91,78,34,62];
var arr2 = [27,64,90,78,34,62];

var max = Math.max.apply(null, arr1);
var min = Math.min.apply(null, arr2);

console.log(max); // 91
console.log(min); // 27

14.数组实现分类统计

🌰 将水果数组中同类的水果合并为一条并求出总数

const fruits = [  
  { name: 'apple', value: 1 }, 
  { name: 'apple', value: 2 },  
  { name: 'banana', value: 2 }, 
  { name: 'banana', value: 3 }
];
  • 方法一: 用reduce()方法进行统计

    使用reduce()方法对水果数组进行遍历和合并操作。在回调函数中,我们定义了一个累加器acc和当前元素curr,并使用一个循环遍历累加器中已有的水果类型。如果当前元素的水果类型已存在于累加器中,则将其数量累加;否则,将当前元素添加到累加器中。

    最后,我们将累加器中的水果类型和数量转换为一个包含对象的数组,并将其打印到控制台。

const result = fruits.reduce(function(acc, curr) {
  var found = false;
  for (var i = 0; i < acc.length; i++) {
    if (acc[i].name === curr.name) {
      acc[i].value += curr.value;
      found = true;
      break;
    }
  }
  if (!found) {
    acc.push({ name: curr.name, value: curr.value });
  }
  return acc;
}, []);

console.log(result);
// 输出:[
//   { name: 'apple', value: 3 },
//   { name: 'banana', value: 5 }
// ]
  • 方法二:使用对象进行归类和统计
// 定义空数组,用于存储统计数据
const fruitTotal = [];  // 存最终数据结果

// 数据按照水果名称进行归类
const nameContainer = {}; // 针对键name进行归类的容器
fruits.forEach(item => {
  nameContainer[item.name] = nameContainer[item.name] || [];
  nameContainer[item.name].push(item);
});

console.log(nameContainer); // 按照水果名称归类完成:{ apple: Array(2), banana: Array(2) }

// 统计不同种类水果的数量
const fruitName = Object.keys(nameContainer); // 获取水果种类:["apple", "banana"]
fruitName.forEach(nameItem => {
  let count = 0;
  nameContainer[nameItem].forEach(item => {
    count += item.value; // 遍历每种水果中包含的条目计算总数
  });
  fruitTotal.push({'name': nameItem, 'total': count});
});

console.log(fruitTotal);
// 输出:[
//   { name: "apple", total: 3 },
//   { name: "banana", total: 5 }
// ]

使用reduce()方法进行统计

  • 优点:

    • 代码量相对较少,逻辑清晰,易于理解。

    • 使用了 ES6 的特性,具有一定的现代化。

  • 缺点:

    • 使用 reduce() 方法需要有一定的函数式编程经验。
    • 由于使用了 reduce() 方法,可能不够直观,需要花费一些时间去理解代码的实现。

使用对象进行归类和统计

  • 优点:

    • 对象直接进行归类和统计,直观易懂,代码易于理解。

    • 可以避免使用reduce()方法时可能出现的问题,如NaN的问题。

    • 可以对每一种水果进行更复杂的操作,如计算平均值等。

  • 缺点:

    • 代码量相对较多,可能不太直观,需要更多的时间去理解代码的实现。
    • 由于使用了对象进行归类和统计,可能会占用较多的内存空间。

15.对象数组根据key重新分组成新的对象数组

  • 方法一
const arr = [
	{ "id": "1001", "name": "值1", "value": "111" },
	{ "id": "1001", "name": "值1", "value": "11111" },
	{ "id": "1002", "name": "值2", "value": "25462" },
	{ "id": "1002", "name": "值2", "value": "23131" },
	{ "id": "1002", "name": "值2", "value": "2315432" },
	{ "id": "1003", "name": "值3", "value": "333333" }
];

function getArrWithKey(originalArr, field) {
  const tempArr = [];
  const endData = [];
  for (let i = 0; i < originalArr.length; i++) {
    if (tempArr.indexOf(originalArr[i][field]) === -1) {
      endData.push({
        [field]: originalArr[i][field],
        data: [originalArr[i]]
      });
      tempArr.push(originalArr[i][field]);
    } else {
      for (let j = 0; j < endData.length; j++) {
        if (endData[j][field] == originalArr[i][field]) {
          endData[j].data.push(originalArr[i]);
          break;
        }
      }
    }
  }
  return endData // 最终输出
}

getArrWithKey(arr, 'name');
// [
//   {
//     "name": "值1",
//     "data": [
//       {"id": "1001","name": "值1", "value": "111"},
//       {"id": "1001","name": "值1", "value": "11111"}
//     ]
//   },
//   {
//     "name": "值2",
//     "data": [
//       {"id": "1002",  "name": "值2", "value": "25462"},
//       { "id": "1002", "name": "值2", "value": "23131"},
//       {"id": "1002","name": "值2","value": "2315432"}
//     ]
//   },
//   {
//     "name": "值3",
//     "data": [
//       {"id": "1003", "name": "值3","value": "333333"}
//     ]
//   }
// ]
  • 方法二

    使用 JavaScriptreduce() 方法将对象数组根据特定的键重新分组为新的对象数组。

const arr = [
  {id: 1, name: 'John', group: 'A'},
  {id: 2, name: 'Jane', group: 'B'},
  {id: 3, name: 'Jim', group: 'A'}
];

const result = Object.entries(arr.reduce((acc, curr) => {
  (acc[curr.group] = acc[curr.group] || []).push(curr);
  return acc;
}, {})).map(([key, value]) => {
  return { group: key, members: value };
});

console.log(result);
//[
//  {
//    group: 'A',
//    members: [
//      {id: 1, name: 'John', group: 'A'},
//      {id: 3, name: 'Jim', group: 'A'}
//    ]
//  },
//  {
//    group: 'B',
//    members: [
//      {id: 2, name: 'Jane', group: 'B'}
//    ]
//  }
//]

16.将具有length属性的对象转成数组

  • 将函数的实际参数转换成数组的方法:

    • 方法一:var args = Array.prototype.slice.call(arguments);

    • 方法二:var args = [].slice.call(arguments, 0);

let toArray = function(s){
  //try语句允许我们定义在执行时进行错误测试的代码块。
  //catch 语句允许我们定义当 try 代码块发生错误时,所执行的代码块。
  try{
    return Array.prototype.slice.call(s);
  } catch(e){
    const arr = [];
    for(let i = 0,len = s.length; i < len; i++){
      //arr.push(s[i]);
      arr[i] = s[i];  //据说这样比push快
    }
    return arr;
  }
}

17. 移除数组中的某一项

function remove (arr, item) {
  if (arr.length) {
    const index = arr.indexOf(item);
    if (index > -1) {
      return arr.splice(index, 1)
    }
  }
}

18. toArray 把类数组转成真正的数组

  • 需求: 把类数组转换成数组,支持从任意位置开始,默认从 0 开始。

    JavaScript 中,有些对象看起来像数组,但是它们没有 Array 原型链上的方法。这些对象被称为类数组对象。

  • 方法:

    如果需要对类数组对象进行数组的操作,需要将其转换为真正的数组。可以使用 JavaScript 中的 Array.from() 方法或者 Array.prototype.slice.call() 方法将类数组对象转换为数组。

function toArray(list, start = 0) {
  const arr = Array.prototype.slice.call(list, start);
  return JSON.parse(JSON.stringify(arr));
}

const arrayLike = { 0: 'foo', 1: 'bar', 2: 'baz', length: 3 };
const arr = toArray(arrayLike, 1);
console.log(arr); // 输出:["bar", "baz"]

// 类数组对象中的元素是对象
const arrayLike1 = { 0: {name: 'foo'}, 1: {name: 'bar'}, length: 2 };
const arr1 = toArray(arrayLike, 0);
console.log(arr1); // 输出:[{name: "foo"}, {name: "bar"}]

需要注意的是,如果类数组对象中的元素包含函数、循环引用等特殊类型的数据,会出现序列化失败的情况。

  • 方法二

    使用数组的下标访问方式,将类数组对象转换为真正的数组。

    与使用 Array.prototype.slice.call() 方法或者 Array.from() 方法相比,该函数的代码更加简洁明了。同时,该函数不需要将方法附加到原型链上,也不需要使用 call 或者 apply 方法调用。

function toArray (list, start = 0) {
  let i = list.length - start; // 计算要转换的元素数量 i
  const ret = new Array(i); // 创建一个空数组 ret
  // 使用 while 循环将类数组对象中的元素复制到新数组中,最终返回新数组 ret
  while (i--) {
    ret[i] = list[i + start];
  }
  return ret
}

// 例子:
function fn(){
  const arr1 = toArray(arguments);
  console.log(arr1); // [1, 2, 3, 4, 5]
  const arr2 = toArray(arguments, 2);
  console.log(arr2); // [3, 4, 5]
}
fn(1,2,3,4,5);

⚠️需要注意的是,如果类数组对象中的元素是对象,使用该方法只是将对象的引用复制到新的数组中,如果需要对数组中的元素进行深拷贝,需要使用其他方法。

19.数组对象转对象

const arr = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 35 }
];

const obj = {};
arr.forEach(item => {
  obj[item.name] = item.age;
});

console.log(obj);
// 输出:{ Alice: 25, Bob: 30, Charlie: 35 }
const arr = [
  { name: 'Alice', age: 25 },
  { name: 'Bob', age: 30 },
  { name: 'Charlie', age: 35 }
];

const obj = arr.reduce((result, item) => {
  result[item.name] = { ...item };
  delete result[item.name].name;
  return result;
}, {});

console.log(obj);
// 输出:{ 
//  Alice: { age: 25 }, 
//  Bob: { age: 30 },
//  Charlie: { age: 35 }
// }

20.将数组中指定的元素挪到第一位

20.1. 普通数组

const arr = [1,2,3,4]
const key = 3

// 方法一:
for (var i = 0; i < arr.length; i++) {
  if (arr[i] === key) {
    arr.splice(i, 1); // 先把符合条件的数据从当前数组中删除
    break;
  }
}
arr.unshift(key); // 通过unshift函数把符合要求的数据放到第一位
console.log(arr); // 输出:[3, 1, 2, 4]

// 方法二:
const index = arr.indexOf(key); // 使用 indexOf 方法获取 key 在数组 arr 中的索引
if (index > 0) {
  arr.splice(index, 1);
  arr.splice(0, 0, x);
}
console.log(arr); // 输出:[3, 1, 2, 4]

20.2. 对象数组

const arr = [
  {id: 1, name: 'Alice'},
  {id: 2, name: 'Bob'},
  {id: 3, name: 'Charlie'},
  {id: 4, name: 'David'},
  {id: 5, name: 'Emily'}
];
const key = 3
let obj = {}; //声明一个对象保存符合要求的数据

// 方法一:
arr.forEach((item,index)=>{
  if(item.id === key){
    obj = item;
    arr.splice(index,1) //先把符合条件的数据从当前数组中删除
    return;
  }
})

arr.unshift(obj); //通过unshift函数把符合要求的数据放到第一位
console.log(arr);

// 方法二:
// 使用 findIndex 方法查找具有指定属性值的元素的索引
const index = arr.findIndex(item => item.id === key); 
if (index > 0) {
  arr.splice(index, 1);
  arr.splice(0, 0, x);
}
console.log(arr);

// 输出:[
//   {
//     "id": 3,
//     "name": "Charlie"
//   },
//   {
//     "id": 1,
//     "name": "Alice"
//   },
//   {
//     "id": 2,
//     "name": "Bob"
//   },
//   {
//     "id": 4,
//     "name": "David"
//   },
//   {
//     "id": 5,
//     "name": "Emily"
//   }
// ]

21.将两个数组合并成一个数组对象

let arr1 = [10, 11, 12]
let arr2 = ['a', 'b', 'c']
let newArr = arr1.map((age, i) => ({age, name: arr2[i]}))
console.log(newArr)
// 输出:[{age: 10, name: 'a'}, {age: 11, name: 'b'}, {age: 12, name: 'c'}]

22.判断数组中的每一层对象的某一个字段属性值不能为空

  • 这种操作一般用来操作列表,提交数据时需要判断某一个字段不能为空等条件。 数组常用操作

  • every, some 遍历数组,区别:every只要有一项不满足条件都返回 falsesome 有一项满足都会返回 true

  • every方法

function checkFieldNotEmpty(arr, fieldName) {
  return arr.every(obj => obj?.[fieldName]);
}
  • some方法
function checkFieldNotEmpty(arr, fieldName) {
  return arr.some(obj => !obj?.[fieldName]);
}
const arr = [
  { name: 'Alice', age: 18 },
  { name: 'Bob', age: null },
  { name: 'Charlie', age: 25 },
];

const fieldName = 'age';
const result = checkFieldNotEmpty(arr, fieldName);

console.log(result); // 输出 true,因为数组中第二个元素的 age 属性值为空

⚠️需要注意的是,使用 everysome 方法时需要保证数组中的每个元素都具有指定的属性,否则在获取不存在的属性时会出现错误。可以通过使用 JavaScript 的可选链操作符?.来避免这种错误,可选链操作符可以在对象属性不存在时直接返回 undefined,而不会导致错误。

转载自:https://juejin.cn/post/7360856203839111219
评论
请登录