Advanced-Frontend / Daily-Interview-Question

我是依扬(木易杨),公众号「高级前端进阶」作者,每天搞定一道前端大厂面试题,祝大家天天进步,一年后会看到不一样的自己。
https://muyiy.cn/question/
27.37k stars 3.3k forks source link

第 11 题:将数组扁平化并去除其中重复数据,最终得到一个升序且不重复的数组 #8

Open zpzxgcr opened 5 years ago

zpzxgcr commented 5 years ago

Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{ return a-b})

inJs commented 5 years ago

@liuliangsir 相反。 concat 可以被替换, apply 是必须的。 这个方法的缺点是有点绕,不好理解。但是兼容性好。

LinSky commented 5 years ago

const flat = (arr) => { return [...new Set(arr.reduce((prev, curr)=>{ return prev.concat(Array.isArray(curr) ? flat(curr) : curr) }, []))].sort((a,b)=>{return a-b}) }

Jingce-lu commented 5 years ago

这样也是可以的:

Array.from(new Set(arr.toString().split(",").sort((a,b)=>{ return a-b}))).map(Number)

huangd-d commented 5 years ago

原题中的Infinity是用来干什么的

flat 参数,来判定需要去重的层数。

peanutYu commented 5 years ago
var arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];

function flatArr(arr, hash = {}) {
  var newArr = [];
  for (var i = 0, len = arr.length; i < len; i++) {
    if (arr[i].constructor === Array) {
      newArr.push(...flatArr(arr[i], hash));
    } else {
      if (!hash[arr[i]]) {
        newArr.push(arr[i]);
        hash[arr[i]] = 1;
      } 
    }
  }
  newArr.sort((a, b) => a - b);
  return newArr;
}

console.log(flatArr(arr));
Tsingwu commented 5 years ago
  var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
  var resArr = [];
  function dealArr(arr) {
    for (var i = 0; i < arr.length; i++) {
      var item = arr[i];
      if (Array.isArray(item)){
        dealArr(item);
      }else{
        if (resArr.indexOf(item) === -1){
          resArr[resArr.length] = item;
        }
      }
    }
  }

  dealArr(arr);

  for (var i = 0; i < resArr.length - 1; i++) {
    for (var j = i + 1; j < resArr.length; j++) {
      if (resArr[i] > resArr[j]){
        var key = resArr[i];
        resArr[i] = resArr[j];
        resArr[j] = key;
      }
    }
  }

  console.log(resArr);
cliYao commented 5 years ago

Array.from(new Set(arr.toString().split(",").sort((a,b)=>{ return a-b}).map(Number))) image

rwjCxgsy commented 5 years ago

arr.toString().split(",").sort((a,b)=>{ return a-b}) 这个想法可以

qiuguixin commented 5 years ago

[...new set(arr.flat())].sort((a,b) => a - b)

qiuguixin commented 5 years ago

[...new Set(arr.toString().split(",").sort((a,b) => a-b).map(Number))]

chaijinsong commented 5 years ago
function flat(arr) {
  let result = [];
  function fn(arr) {
    if (Array.isArray(arr)) {
      arr.forEach((item)=> {
        fn(item);
      })
    } else {
      result.push(arr);
    }
  }
  fn(arr);
  return [...new Set(result)].sort((a, b) => { return a - b; });
}
fengyun2 commented 5 years ago

arr.toString().split(",").sort((a,b)=>{ return a-b})

这种会丢失原来的数据类型吧

lentoo commented 5 years ago

[...new Set(arr.flat(Infinity))].sort((a, b) => a -b )

Forx-Js commented 5 years ago
function arrayFlat(list = []) {
  return [...new Set(function (arr) {     //去重
    const newArr = Array.prototype.concat.apply([], arr)  //扁平化
    return newArr.some(Array.isArray) ? arguments.callee(newArr) : newArr;    //递归
  }(list))]
  .sort((a, b) =>a - b)  //排序
toringo commented 5 years ago
    const arr = [[1, 3, 13, 1, 14], [2, 3, 4, 5], [6, 6, 7, 8, [10, 11, 21, [14]]]];

    function flatArr(arr, nodelist = []) {
      return arr.reduce((total, item) => {
        if (Array.isArray(item)) {
          flatArr(item, total);
        } else {
          total.push(item);
        }
        return total;
      }, nodelist)
    }

    const newArr = [...new Set(flatArr(arr))].sort((a, b) => a - b);
zxl-lxz commented 5 years ago
[...new Set(arr.flat(Infinity)].sort((a, b) => a-b);
zz026 commented 5 years ago

[...new Set(arr.flat(Infinity))].sort((a, b) => a - b)

5SSS commented 5 years ago
var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
var map = {};
var res = []
function depth (arr) {
    arr.forEach(item => {
        if (item instanceof Array) {
            depth(item)
        } else {
            map[item] = item
        }
    })
}
depth(arr)
for (let key in map) {
    res.push(parseInt(key))
}
res = res.sort((a, b) => a - b)
console.log(res)
//  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
liujuntao123 commented 5 years ago
var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
var map = {};
var res = []
function depth (arr) {
  arr.forEach(item => {
      if (item instanceof Array) {
          depth(item)
      } else {
          map[item] = item
      }
  })
}
depth(arr)
for (let key in map) {
  res.push(parseInt(key))
}
res = res.sort((a, b) => a - b)
console.log(res)
//  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

感觉既然是算法题,这个应该是正解才对,我写出来的几乎跟你一样,而且我还在考虑sort是否也要手动的实现。 image

BiYuqi commented 5 years ago
const flatten = arr => arr.reduce((acc, item) =>
    acc.concat(Array.isArray(item) ? flatten(item) : item), [])
const sw = arr => Array.from(new Set(flatten(arr))).sort((a, b) => a - b)
const arr = [[1,21],3,[40,5,[6,[7,8,[90,10]]]]]
console.log(sw(flat))
//  [1, 3, 5, 6, 7, 8, 10, 21, 40, 90]
lhyt commented 5 years ago
[...new Set(JSON.parse(`[${arr}]`).sort((a, b) => a - b))]
lhyt commented 5 years ago

如果重复的数都是连着的

JSON.parse( `[${`${arr}`.replace(/\b(\d+),\1/g, '$1')}]`).sort((a, b) => a - b)
nailfar commented 5 years ago

原题中的Infinity是用来干什么的

目测是用来指定要扁平化数组的层数

zz026 commented 5 years ago

原题中的Infinity是用来干什么的

flat() 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。 参数是 要提取嵌套数组的结构深度,默认值为 1。

fireairforce commented 5 years ago

这个题面试的时候真的遇到了,用递归写了。

francecil commented 5 years ago

考虑到元素可能不止数字,排序时候稍微改下

[...new Set(arr.flat(Infinity))].sort((a,b)=>+(a>b)||+(a===b)-1)
liuchao2019 commented 5 years ago

var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]; var obj = {}; function deepClone(arr) { var attr = []; arr.forEach(function (v) { if (v.constructor === Array) { attr = attr.concat(deepClone(v)); } else { if (obj[v] === undefined) { obj[v] = v; attr.push(v); } } }); return attr; }

    console.log(deepClone(arr).sort(function (a, b) {
        return a - b;
    }))
liyixun commented 5 years ago
    let arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
    let tempArray = arr.flat(); // 保存每次flat后的数组
    while(checkArrayItemHasArray(tempArray)) {
        tempArray = tempArray.flat();
    }
    tempArray = Array.from(new Set([...tempArray]));    // 去重
    tempArray = tempArray.sort((a, b) => a - b);        // 排序
    console.log(tempArray);

    // 判断数组项是否有数组类型
    function checkArrayItemHasArray(arr) {
        let result = false;
        for(let i = 0; i < arr.length; i++) {
            if (Array.isArray(arr[i])) {
                result = true;
                break;
            }
        }
        return result;
    }
jarbinup commented 5 years ago
var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];

function flattern(arg){
    if(!Array.isArray(arg)) return false;
    const arr = arg.reduce((prev, next)=>{
        return prev.concat(Array.isArray(next) ? flattern(next) : next)
    }, [])

    return arr;
}

function unique(arg){
    return Array.from(new Set(arg))
}

function sortArr(arg) {
    const arr = arg.sort((a, b) => {
        return a-b;
    })
    return arr
}

sortArr(unique(flattern(arr)));

第一印象写出来的,原生方法 arr.flat(arg) 参数表示要展开的层级,默认也是全部展开 Infinity 全部展开。
改进地方, 参考前面的答案可以把方法挂载到原型 Array.prototype 上,实现链式调用 
Alvin1992 commented 5 years ago
var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
var map = {};
var res = []
function depth (arr) {
    arr.forEach(item => {
        if (item instanceof Array) {
            depth(item)
        } else {
            map[item] = item
        }
    })
}
depth(arr)
for (let key in map) {
    res.push(parseInt(key))
}
res = res.sort((a, b) => a - b)
console.log(res)
//  [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

感觉既然是算法题,这个应该是正解才对,我写出来的几乎跟你一样,而且我还在考虑sort是否也要手动的实现。 image

用了递归扁平,hash去重,冒泡排序,打开讨论区大吃一惊

yondYS commented 5 years ago

var arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]; var res = []; var obj = {}; //扁平时去重 function flattenDeep(arr){ var target; var i = 0; for(;i < arr.length;i++){ target = arr[i]; if(Array.isArray(target)){ flattenDeep(target); }else{ //用对象来过滤重复的数据(空间换时间) if(!obj[target]){ obj[target] = target; res.push(target); } } } } flattenDeep(arr); console.log(res.sort(function(a,b){return a - b}));

Bryce-Lin commented 5 years ago

[...new Set(arr.flat(Infinity))].sort((a,b)=>a-b)

MinosIE commented 5 years ago

`var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10 ];

const arrHandel = arr => [...new Set(arr.flat(Infinity))].sort((a, b) => a - b); console.log(arrHandel(arr));`

fitbye commented 5 years ago

[...new Set(arr.toString().split(','))].sort((x, y) => x - y)

lijiayi01 commented 5 years ago
// 扁平化数组方法

function formatArr(arr) {
    return arr.reduce((result, item) => {
        return result.concat(item instanceof Array ? formatArr(item) : item)
    }, [])
}

// 数组去重

function noRepeat(arr) {
    var obj = {}
    var newArr= []
    arr.forEach((item, key) => {
        if( !obj[item]){
            newArr.push(item);
            obj[item] = true
        }
    })
    return newArr;
}

var arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];

// 将相关方法统一
function unionArr(arr){
    var arr1 = formatArr(arr);
    var arr2 = noRepeat(arr1);

    arr2.sort((a, b)=>{
        return a - b
    })

    return arr2;

}
console.log(unionArr(arr))
zz026 commented 5 years ago

[... new Set(arr.toString()。split(','))]。sort((x,y)=> x - y) 这样变成字符串了哈,加了一步 [...new Set(arr.toString().split(','))].map(val => Math.floor(val)).sort((x, y) => x - y)

1213204205 commented 5 years ago

var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]; let Array = Array.from(new Set(arr.join(',').split(',').sort((a,b) => {return a-b}))).map(Number)

NathanHan1 commented 5 years ago

前面的答案都是直接来这些高级方法,其实我是面试官,可能更愿意看到: sort,你能直接写个快排 扁平化,知道使用递归 去重,知道set结构并且自己实现一个set

最后,用函数式把这些串起来 这才perfect呀

savoygu commented 5 years ago
// 实现:
const flat = (data) => data.reduce((acc, val) => Array.isArray(val) ? acc.concat(flat(val)) : acc.concat(val), [])
const unique = data => data.reduce((acc, val) => acc.indexOf(val) > -1 ? acc : acc.concat(val), [])
const sort = (data, order) => data.sort((a, b) => order === 'desc' ? b - a : a - b)
const compose = (...fns) => fns.reduce((f, g) => (...args) => f(g(...args)))
const bindRight = (fn, thisObj, ...values) => (...args) => (len = fn.length - values.length, fn.apply(thisObj, args.slice(0, len > 0 ? len : 0).concat(values.reverse())))
// 数据:
const arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
// 验证:正序
console.log(compose(sort, unique, flat)(arr))
// 输出:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
// 验证:倒序
console.log(compose(bindRight(sort, null, 'desc'), unique, flat)(arr))
// 输出:
[14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
Livre1431 commented 5 years ago
一种方法:[...new Set(arr.toString().split(','))].sort((a, b)=>{return a-b}).map(Number)
还有:[...new Set(arr.flat(Infinity))].sort((a,b)=>{return a- b})
Jimi1126 commented 5 years ago

捕获

tongchuan commented 5 years ago

[... new Set(arr.flat(Infinity))].sort((a,b)=>a-b)

gezi666 commented 5 years ago

arr.toString()。split(“,”)。sort((a,b)=> {return ab})

你可能后面需要 arr.toString().split(",").sort((a,b)=>{ return a-b}).map(Number) 不然数组元素都是字符串 结果并没有去重 还有两个2 5和12

[... new Set(arr.toString().split(",").sort((a,b)=>{ return a-b}).map(Number))]

udbbbn commented 5 years ago

// 递归方式 数组扁平化

var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
function flat(arr) {
    let _arr = Array.from(arr);
    let res = [];
    _arr.map(el => {
        if (el instanceof Array) {
            res = res.concat(flat(el))
        } else {
            res.push(el)
        }
    })
    return res
}

答案为: [...new Set(flat(arr))].sort((a,b)=>{return a - b})

YOMXXX commented 5 years ago

Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{ return a-b})

这个目前低版本浏览器是不支持的 需要es7 babel支持

gezi666 commented 5 years ago

现在项目基本都会用babel-polyfill去做转码的

------------------ 原始邮件 ------------------ 发件人: "Angular"notifications@github.com; 发送时间: 2019年7月10日(星期三) 上午10:30 收件人: "Advanced-Frontend/Daily-Interview-Question"Daily-Interview-Question@noreply.github.com; 抄送: "每一天"3129168699@qq.com; "Comment"comment@noreply.github.com; 主题: Re: [Advanced-Frontend/Daily-Interview-Question] 第 11 题:将数组扁平化并去除其中重复数据,最终得到一个升序且不重复的数组 (#8)

Array.from(new Set(arr.flat(Infinity))).sort((a,b)=>{ return a-b})

这个目前低版本浏览器是不支持的 需要es7 babel支持

— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.

imccode commented 5 years ago
Array.from(new Set(arr.flat(Infinity))).sort((a, b) => a - b)
arixse commented 5 years ago

发一个不是很成熟的解决方法 :

function flat(arr) {
    let result = [];
    arr.forEach(a=>{
        if(Array.isArray(a)) {
            result = [...result,...flat(a)]
        } else {
            result.push(a);
        }
    })
    return [...new Set(result)].sort((a,b)=>a-b)
}
LoopFlying commented 5 years ago

@zpzxgcr 测试结果,如果将Array1.flat(Infinity)替换为:Array2.toString().split(',') #能省300多ms

sqrtqiezi commented 5 years ago
arr.flat(Infinity)
  .sort((a, b) => a - b)
  .filter((item, index, arr) => index == 0 || arr[index-1] != item)