Advanced-Frontend / Daily-Interview-Question

我是依扬(木易杨),公众号「高级前端进阶」作者,每天搞定一道前端大厂面试题,祝大家天天进步,一年后会看到不一样的自己。
https://muyiy.cn/question/
27.34k stars 3.29k 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})

zpzxgcr commented 5 years ago

image

zpzxgcr commented 5 years ago
相关知识点

es6数组常用操作

hejiaqian commented 5 years ago
arr.toString().split(",").sort((a,b)=>{ return a-b})
hejiaqian commented 5 years ago

image

zpzxgcr 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

hejiaqian commented 5 years ago

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

你可能后面需要 arr.toString().split(",").sort((a,b)=>{ return a-b}).map(Number) 不然数组元素都是字符串

谢谢大佬指点,学习了

cjfff commented 5 years ago
Array.prototype.flat= function() {
    return [].concat(...this.map(item => (Array.isArray(item) ? item.flat() : [item])));
}

Array.prototype.unique = function() {
    return [...new Set(this)]
}

const sort = (a, b) => a - b;

console.log(arr.flat().unique().sort(sort)); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ]
AprilTong commented 5 years ago
var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
function flatten(arr) {

    while (arr.some(item => Array.isArray(item))) {
        arr = [].concat(...arr);
    }

    return arr;
}
Array.from(new Set(flatten(arr))).sort((a, b) => {
 return a - b
})
zpzxgcr commented 5 years ago
Array.prototype.falt = function() {
    return [].concat(...this.map(item => (Array.isArray(item) ? item.falt() : [item])));
}

Array.prototype.unique = function() {
    return [...new Set(this)]
}

const sort = (a, b) => a - b;

console.log(arr.falt().unique().sort(sort)); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ]

函数名应该是flat

cjfff commented 5 years ago
Array.prototype.falt = function() {
    return [].concat(...this.map(item => (Array.isArray(item) ? item.falt() : [item])));
}

Array.prototype.unique = function() {
    return [...new Set(this)]
}

const sort = (a, b) => a - b;

console.log(arr.falt().unique().sort(sort)); // [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 ]

函数名应该是flat

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

// 数组拍平
var level_arr=old_arr.flat(4);

//数组去重
var Distinct=Array.from(new Set(level_arr));

// 排序
var sort=  Distinct.sort((a, b) =>a - b)

console.log("new arr",sort)
jackchenl commented 5 years ago

递归函数解法:

function spreadArr(arr=[]){
    if(arr.some(ele=>Array.isArray(ele))){
        let newArr = [];
        arr.forEach((ele) => {
            if(Array.isArray(ele)){
                newArr = newArr.concat(...ele)
            }else{
                if(!newArr.includes(ele)) newArr.push(ele)
            }
        })
        return spreadArr(newArr);
    }
    return arr.sort((a,b)=> a-b);
}
spreadArr([ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]);
zhuzhuoxingguang commented 5 years ago

利用前面的答案,修正一个没用ES6的写法:

// 1、扁平化数组 var flatArr = arr.toString().split(","); // 2、去重 var hash = {}; for (var i = 0, len = flatArr.length; i < len; i++) { hash[flatArr[i]] = "abc" } flatArr = []; // 3、将元素字符串转化为数字、遍历hash并不能保证输出顺序 for (var i in hash) { flatArr.push(+i) } // 4、排序 flatArr = flatArr.sort(function(a, b) { return a - b }) console.log(flatArr)

sisterAn commented 5 years ago

看一道面试题:

已知如下数组:var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];

编写一个程序将数组扁平化去并除其中重复部分数据,最终得到一个升序且不重复的数组

答案:

var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10]
// 扁平化
let flatArr = arr.flat(4)
// 去重
let disArr = Array.from(new Set(flatArr))
// 排序
let result = disArr.sort(function(a, b) {
    return a-b
})
console.log(result)
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]

关于 Set 请查阅 Set、WeakSet、Map及WeakMap

本文首发于我的博客:数组扁平化、去重、排序

xiaoluoboding commented 5 years ago

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

wangweianger commented 5 years ago

01 [...new Set(arr.toString().split(','))].sort((a,b)=>a-b)

Allen3039 commented 5 years ago

额 虽然没大佬们厉害,暂且做个记录吧


function flap(arr){
  if([].every.call(arr,item=>!Array.isArray(item))){
    return arr; 
  }
  return [].reduce.call(arr,(pre,cur)=>{
    if(Array.isArray(cur)){
      return [].concat(pre,flap(cur));
    }else{
      return [].concat(pre,cur);
    }
  },[])
}

function removeRepeat(arr){
  return [...new Set(arr)];
}

function sort(arr){
  return [].sort.call(arr,(a,b)=>a-b)
}

function handle(data,...fns){
  return fns.reduce((pre,cur)=>{
      return cur(pre);
  },data)
}

handle(arr,flap,sort,removeRepeat);
xpbsm commented 5 years ago

arr.join(','),split(','),sort((a,b) => a - b)

mydaoyuan commented 5 years ago

拍平: const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v))); 用toString会改变数组里面的原始数据,应该会是扣分项。

ihuoge commented 5 years ago

1550544432 1

Jason686 commented 5 years ago
Array.from(new Set(arr.toString().split(',').map(Number))).sort((a, b) => (a-b))
hellojackhui commented 5 years ago
  1. 拍平数组:const flatArray = arr => arr.reduce((a,b) => a.concat(Array.isArray(b) ? flatArray(b): b), []);
  2. 去重+排序: [...new Set(flatArray)].sort((a,b) => a-b);
fan-2 commented 5 years ago

image

yishuihan-001 commented 5 years ago

var arr = [...new Set(arr.join(',').split(','))].map(v => Number(v)).sort((a,b) => a-b)

xiaochen111 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 arrDef(arr) {
      if(arr instanceof Array){
        arrforDef(arr)
      }else {
        obj[arr] = 1;
      }
  }

  function arrforDef(arr){
    arr.forEach( function(element, index) {
       arrDef(element)
    });
  }

  arrDef(arr);
  console.log(Object.keys(obj))
mySouler commented 5 years ago

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

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

function flat (arr) {
  function toFlat (acc, current) {
    if (Object.prototype.toString.call(current) === '[object Array]') {
      current.forEach(item => {
        toFlat(acc, item)
      })
    } else {
      if (!acc.includes(current)) {
        acc.push(current)
      }
    }
    return acc
  }
  return arr.reduce(toFlat, []).sort((value1, value2) => value1 - value2)
}

flat(arr)

利用Array.prototype.reduce函数递归进行函数拍平去重加排序。这个咋样?

weiweixuan commented 5 years ago

// 已知如下数组: var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10 ]; // 编写一个程序将数组扁平化去并除其中重复部分数据,最终得到一个升序且不重复的数组

    // // 去扁平化
    function paiping(arr){
        if(Array.isArray(arr)){
            let arr_ = [];
            digui(arr,arr_);
            return arr_;
        }
    }
    // 递归
    function digui(arr_item,arr_){
        for(let i=0;i<arr_item.length;i++){
                if(Array.isArray(arr_item[i])){
                    digui(arr_item[i],arr_);
                }else{
                    arr_.push(arr_item[i]);
                }
            }
    }
    let res =[...new Set(paiping(arr).sort((a,b)=>a-b))];
    console.log(res);
    // 方法二
   let res2 =[...new Set(arr.toString().split(",").map((items)=>{
      return parseInt(items);
   }).sort((a,b)=>a-b))] ;
   console.log(res2);
xifenzs commented 5 years ago

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

xiangergou commented 5 years ago

[...new Set(arr.toString().split(',').map(k => +k))].sort((a, b) => a-b)

chiwent commented 5 years ago

个人拙见:

function flatten(arr) {
  return arr.reduce(function (flat, toFlatten) {
    return flat.concat(Array.isArray(toFlatten) ? flatten(toFlatten) : toFlatten);
  }, []).sort((a, b) => a - b).filter (function (value, index, array) { 
    return array.indexOf (value) == index;
});
}

image

ghost commented 5 years ago

我觉得最好不要在 built-in 函数的 prototype 上直接加方法 而且有些方法命名不太规范,比如 const sort = (a, b) => a - b;,我觉得命名为 comparator 比较合理。另外,还有函数命名为 flatten,我觉得 flat 可能会更好


const arr = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14]]]], 10];
Array.from(new Set (arr.toString().split(',')), val => +val).sort((a, b) => a - b)

toString 用在这里确实不太合适。因为 tostring 会把数组里面的元素会变成 string 类型。比如,对象类型的数组元素({a: 1})会变成 [object Object] 以及函数类型的数组元素(new Function('a', 'b', 'return a - b'))会变成 function anonymous(a,b) {return a - b}

lianxiaonm commented 5 years ago
const arr1 = (arr + '').split(',')
[...new Set(arr1)].sort((a,b)=>a-b)
ZQ-jhon commented 5 years ago

const set = new Set([ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10].flat(Infinity)); const arr = Array.from(set); arr.sort((a,b) => a - b);

dengnan123 commented 5 years ago
总结方法就是以下几种方式:1. es6 2. reduce 3. 递归 4. toString
shizhenbin commented 5 years ago

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

this is good

juwuyu commented 5 years ago

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

  1. split()方法是把字符串分割成字符数组,所以最后的排序是根据字符串的编码来排序,输出的也是字符串数组
  2. 这个方法也没有去重

set方法去重,flat方法扁平化,最后把对象转化成数组:

var arry =[1,25,15,[1,2,15,5],15,25,35,1];
var set =new Set(arry.flat(Infinity).sort((a,b)=>(a-b)));
var arr= [...set];
:
console.log(arr)// [1, 2, 5, 15, 25, 35]

参考https://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/0014345007434430758e3ac6e1b44b1865178e7aff9082e000/

thinkfish commented 5 years ago

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

Frank-zf commented 5 years ago

image

twoyoung6 commented 5 years ago

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

1、.toString().split(',') 扁平化数据; 2、sort() 排序数据; 3、map(Number) 转数字; 4、Array.from(new Set()) 去重;

inJs commented 5 years ago

为什么没有人提 利用 apply 做数组降维 呢?

简单实现,不考虑 depth=Infinity 的情况

const flat = function(ary, depth) {
  let flatedAry = ary

  while(depth > 0) {
     flatedAry = [].concat.apply([], flatedAry)

     depth--
  }

  return flatedAry
}

再结合 Set 去重、sort 排序。 美滋滋呢~

另外, toString 的降维方式并不认同,原因是不严谨。

zhoufanglu commented 5 years ago

[...arr.join().split(',')].sort(a,b) join() 数组转为字符串 split 字符串 转为数组 [...]去重 我个人觉得这个是最简单的

faber-pan commented 5 years ago

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

jjeejj commented 5 years ago

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

这里的 sort 里面的排序函数可以省略,直接使用 sort, 默认就是升序排列 Array.from(new Set(arr.flat(Infinity))).sort()

BaconZhang commented 5 years ago

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

const flat = (array) => [].concat(...array.map(i => Array.isArray(i) ? flat(i) : [i]));

const unique = (array) => [...new Set(array)];

const sort = (array) => array.sort((a, b) => a - b);

const compose = (...fns) => value => [...fns].reduceRight((prev, fn) => prev = fn(prev), value);

compose(sort, unique, flat)(arr);

ghost commented 5 years ago

@BaconZhang 为啥不用 reduceRight?因为我觉得 reduceRight 比 reduce 更符合语义

BaconZhang commented 5 years ago

@liuliangsir 感谢指正,这里使用reduceRight比reverse加reduce更简洁

ghost commented 5 years ago

@inJs apply 作用是用来降维?apply 之所以能够用来降维,是因为你借用 concat 函数吧 @BaconZhang 其实我觉得代码还是有点问题,compose(sort, unique, flat)(arr); 这种写法不太符合 pipe 理念,而且 (prev, fn) => prev = fn(prev) 这里有点问题,不需要把 fn(prev) 重新赋给 prev,可以参考 reduce 或者 reduceRight 的实现

这是我实现的 compose

function compose(...funcs) {
    return function (...args) {
        return funcs.reduceRight((prev, func) => Array.isArray(prev) ? func(...prev) : func(prev), args);
    };
}
fingerpan commented 5 years ago

@liuliangsir compose 和 pipe 是两种思路。pipe(flow)是从前到后,compose是从后到前。

KaiOrange commented 5 years ago
var arr = [ [1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13, [14] ] ] ], 10];
arr.toString().split(",").filter((item,index,arrs)=>(arrs.indexOf(item) === index)).sort((a,b)=>a-b);