動態

詳情 返回 返回

數組並集/交集/差集 - 動態 詳情

underscore

官網

_.union([2,1,2]); // [2,1]

lodash

官網

_.uniq([2,1,2]); [2,1]

不產生新數組

使用indexOf判斷和splice刪除。

const removeDuplicates = (nums) => {
    let len = nums.length - 1
    for(let i = len; i>=0; i--) {
        if(nums.indexOf(nums[i]) != i) {
            nums[i] = nums[len --]
        }
    }
    // 刪除重複項
    nums.splice(len+1)
    return nums
}
// 測試
removeDuplicates([1, 2, 3, 1, 3])
// [1, 2, 3]

reduce

function unique (arr) {
    return arr.sort().reduce((acc, cur) => {
     if (acc.length === 0 || acc[acc.length - 1] !== cur) {
         acc.push(cur);
     }
     return acc
 }, [])}
;

// 測試
var arr = [1, 2, 2, 3]
unique(arr); // [1, 2, 3]

filter

function unique(arr) { 
    return arr.filter( (element, index, array) => {
     return array.indexOf(element) === index
 })
}

// 測試
var arr = [1, 2, 2, 3]
unique(arr); // [1, 2, 3]

ES5

ES5可以利用filterindexOf和進行數學集操作,但是,由於indexOf方法中NaN永遠返回-1,所以需要進行兼容處理。

var a = [1,2,3];
var b = [1,2,2,4];

//並集(去重)
var union = a.concat(b.filter(function(v) {return a.indexOf(v) === -1 } )); // [1,2,3,4]
//交集
var intersection = a.filter(function(v){ return b.indexOf(v) > -1 }); // [1,2]
//差集
var difference = a.filter(function(v){ return b.indexOf(v) === -1 }); // [3]

ES6

ES6中新增的一個Array.from方法,用於將類數組對象和可遍歷對象轉化為數組。只要類數組有length長度,基本都可以轉化為數組。結合Set結構實現數學集求解。

let a = [1,2,3];
let b = [1,2,2,4];

let aSet = new Set(a);
let bSet = new Set(b);

//並集(去重)
let union = Array.from(new Set(a.concat(b))); // [1,2,3,4]
//交集
let intersection = Array.from(new Set(a.filter(v => bSet.has(v)))); // [2]
//差集
let differenceNew = Array.from(new Set(a.concat(b).filter(v => aSet.has(v) && !bSet.has(v))); // [3]

ES7

ES7新增了一個Array.prototype.includes的數組方法,用於返回一個數組是否包含指定元素,結合filter方法。

let a = [1,2,3];
let b = [1,2,2,4];

//並集(去重)
let union = a.concat(b.filter(v => !a.includes(v))); // [1,2,3,4]
//交集
let intersection = a.filter(v => b.includes(v)); // [1,2]
//差集
let difference = a.concat(b).filter(v => a.includes(v) && !b.includes(v)); // [3]

數組扁平化(數組降維)

MDNflat()方法會按照一個可指定的深度遞歸遍歷數組,並將所有元素與遍歷到的子數組中的元素合併為一個新數組返回。

const test = ["a", ["b", "c"], ["d", ["e", ["f"]], "g"]]

// flat不傳參數時,默認扁平化一層
test.flat()
// ["a", "b", "c", "d", ["e", ["f"]], "g"]

// flat傳入一個整數參數,整數即扁平化的層數
test.flat(2)
// ["a", "b", "c", "d", "e", ["f"], "g"]

// Infinity 關鍵字作為參數時,無論多少層嵌套,都會轉為一維數組
test.flat(Infinity)
// ["a", "b", "c", "d", "e", "f", "g"]

// 傳入 <=0 的整數將返回原數組,不扁平化
test.flat(0)
test.flat(-1)
// ["a", ["b", "c"], ["d", ["e", ["f"]], "g"]]

// 如果原數組有空位,flat()方法會跳過空位。
["a", "b", "c", "d",,].flat()
// ["a", "b", "c", "d"]

Array.prototype.flat()

  • Array.prototype.flat() 用於將嵌套的數組扁平化,成為一維數組。該方法返回一個新的數組,對原數據沒有影響
  • 不傳參數時,默認扁平化一層;傳入一個整數時,這個整數代碼想要扁平化的層數
  • 傳入 <=0 的整數將不進行扁平化,返回原數組
  • Infinity 關鍵字作為參數時,無論是多少層嵌套,都會轉為一維數組
  • 另外,注意:如果原數組有空位,Array.prototype.flat() 會跳過空位

手寫扁平化函數

一、使用reduce方法

function flattenDeep(arr) { 
    return Array.isArray(arr)
      ? arr.reduce( (acc, cur) => [...acc, ...flattenDeep(cur)] , [])
      : [arr]
}

// 測試
var test = ["a", ["b", "c"], ["d", ["e", ["f"]], "g"]]
flattenDeep(test)
// ["a", "b", "c", "d", "e", "f", "g"]

實現flat函數:

function flat(arr, depth = 1) {
    return depth > 0
        ? arr.reduce((acc, cur) => {
        if(Array.isArray(cur)) {
            return [...acc, ...flat(cur, depth-1)]
        }
        return [...acc, cur]
    } , [])
      : arr
}

// 測試
var test = ["a", ["b", "c"], ["d", ["e", ["f"]], "g"]]
// 不傳參數時,默認扁平化一層
flat(test)
// ["a", "b", "c", "d", ["e", ["f"]], "g"]

// 傳入一個整數參數,整數即扁平化的層數
flat(test, 2)
// ["a", "b", "c", "d", "e", ["f"], "g"]

// Infinity 關鍵字作為參數時,無論多少層嵌套,都會轉為一維數組
flat(test, Infinity)
// ["a", "b", "c", "d", "e", "f", "g"]

// 傳入 <=0 的整數將返回原數組,不扁平化
flat(test, 0)
flat(test, -10)
// ["a", ["b", "c"], ["d", ["e", ["f"]], "g"]];

// 如果原數組有空位,flat()方法會跳過空位。
var arr = ["a", "b", "c", "d",,]
flat(arr)
// ["a", "b", "c", "d"]

二、棧

function flattenDeep(arr) {
  const result = [] 
  // 將數組元素拷貝至棧,直接賦值會改變原數組
  const stack = [...arr]
  // 如果棧不為空,則循環遍歷
  while (stack.length !== 0) {
    const val = stack.pop() 
    if (Array.isArray(val)) {
      // 如果是數組再次入棧,並且展開了一層
      stack.push(...val) 
    } else {
      // 如果不是數組,就用頭插法插入到結果數組中
      result.unshift(val)
    }
  }
  return result
}

// 測試
var test = ["a", ["b", "c"], ["d", ["e", ["f"]], "g"]]
flattenDeep(animals)
// ["a", "b", "c", "d", "e", "f", "g"]

參考來源:

https://mp.weixin.qq.com/s/VRjEtRYj6mvp2-YW4iKMdQ

https://mp.weixin.qq.com/s/NGl9nBkIruuzYkxqyPnB1A

Add a new 評論

Some HTML is okay.