Eason

Eason 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织 github.com 编辑
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

Eason 赞了问题 · 2020-05-27

解决Model, Orm, Dao 和 Active Record 的异同点

Model, Orm, Dao 和 Active Record 的异同点,求高手解释,可以基于现在 PHP 的流行框架。能举例更好啦!

关注 5 回答 5

Eason 赞了回答 · 2020-03-13

如何理解HTTP PATCH是非幂等的?

所谓幂等,通俗来讲就是不管执行多少次,所造成的后果都一样,比如 DELETE /my/resource/123 不管执行多少遍都是删除 123 这个资源,不会造成把 456 给删了;再如 POST /my/resource 数据 name=张三&age=60 每执行一次就加一个张三,这是非幂等的。那回到 PATCH 上,如何理解它是非幂等呢,功能是更新部分内容没错,但对它的定义这个是不全的,完整描述如下:

The PATCH Method

The PATCH method requests that a set of changes described in the
request entity be applied to the resource identified by the Request-
URI. The set of changes is represented in a format called a "patch
document" identified by a media type. If the Request-URI does not
point to an existing resource, the server MAY create a new resource,
depending on the patch document type (whether it can logically modify
a null resource) and permissions, etc.

其中有很重要一句说明,如果 URI 对应的资源不存在,服务端可以创建一个新资源。

详见 https://tools.ietf.org/html/r...

关注 4 回答 2

Eason 收藏了问题 · 2020-01-14

在HTTP请求的header头里面,为什么有的时候有X-Powered-By这个值,有的时候没有呢?

在HTTP请求的header头里面,为什么有的时候有X-Powered-By这个值,有的时候没有呢?

Eason 收藏了文章 · 2019-11-02

ELF文件解析(一):Segment和Section

ELF 是Executable and Linking Format的缩写,即可执行和可链接的格式,是Unix/Linux系统ABI (Application Binary Interface)规范的一部分。

Unix/Linux下的可执行二进制文件、目标代码文件、共享库文件和core dump文件都属于ELF文件。

下面的图来自于文档 Executable and Linkable Format (ELF),描述了ELF文件的大致布局。
Elf文件的大致布局

左边是ELF的链接视图,可以理解为是目标代码文件的内容布局。右边是ELF的执行视图,可以理解为可执行文件的内容布局。
注意目标代码文件的内容是由section组成的,而可执行文件的内容是由segment组成的。

要注意区分段(segment)和节(section)的概念,这两个概念在后面会经常提到。
我们写汇编程序时,用.text,.bss,.data这些指示,都指的是section,比如.text,告诉汇编器后面的代码放入.text section中。
目标代码文件中的section和section header table中的条目是一一对应的。section的信息用于链接器对代码重定位。

而文件载入内存执行时,是以segment组织的,每个segment对应ELF文件中program header table中的一个条目,用来建立可执行文件的进程映像。
比如我们通常说的,代码段、数据段是segment,目标代码中的section会被链接器组织到可执行文件的各个segment中。
.text section的内容会组装到代码段中,.data, .bss等节的内容会包含在数据段中。

在目标文件中,program header不是必须的,我们用gcc生成的目标文件也不包含program header。
一个好用的解析ELF文件的工具是readelf。对我本机上的一个目标代码文件sleep.o执行readelf -S sleep.o,输出如下:

There are 12 section headers, starting at offset 0x270:

Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .text             PROGBITS         0000000000000000  00000040
       0000000000000015  0000000000000000  AX       0     0     1
  [ 2] .rela.text        RELA             0000000000000000  000001e0
       0000000000000018  0000000000000018   I       9     1     8
  [ 3] .data             PROGBITS         0000000000000000  00000055
       0000000000000000  0000000000000000  WA       0     0     1
  [ 4] .bss              NOBITS           0000000000000000  00000055
       0000000000000000  0000000000000000  WA       0     0     1
  ... ... ... ...
  [11] .shstrtab         STRTAB           0000000000000000  00000210
       0000000000000059  0000000000000000           0     0     1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)

readelf -S是显示文件中的Section信息,sleep.o中共有12个section, 我们省略了其中一些Section的信息。
可以看到,除了我们熟悉的.text, .data, .bss,还有其它Section,这等我们以后展开讲Section的时候还会专门讲到。
看每个Section的Flags我们也可以得到一些信息,比如.text section的Flags是AX,表示要分配内存,并且是可执行的,这一节是代码无疑了。
.data 和 .bss的Flags的Flags都是WA,表示可写,需分配内存,这都是数据段的特征。

使用readelf -l可以显示文件的program header信息。我们对sleep.o执行readelf -l sleep.o。会输出There are no program headers in this file.
program header和文件中的segment一一对应,因为目标代码文件中没有segment,program header也就没有必要了。

可执行文件的内容组织成segment,因此program header table是必须的。
section header不是必须的,但没有strip过的二进制文件中都含有此信息。
对本地可执行文件sleep执行readelf -l sleep,输出如下:

Elf file type is DYN (Shared object file)
Entry point 0x1040
There are 11 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
  PHDR           0x0000000000000040 0x0000000000000040 0x0000000000000040
                 0x0000000000000268 0x0000000000000268  R      0x8
  INTERP         0x00000000000002a8 0x00000000000002a8 0x00000000000002a8
                 0x000000000000001c 0x000000000000001c  R      0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000560 0x0000000000000560  R      0x1000
  LOAD           0x0000000000001000 0x0000000000001000 0x0000000000001000
                 0x00000000000001d5 0x00000000000001d5  R E    0x1000
  LOAD           0x0000000000002000 0x0000000000002000 0x0000000000002000
                 0x0000000000000110 0x0000000000000110  R      0x1000
  LOAD           0x0000000000002de8 0x0000000000003de8 0x0000000000003de8
                 0x0000000000000248 0x0000000000000250  RW     0x1000
  DYNAMIC        0x0000000000002df8 0x0000000000003df8 0x0000000000003df8
                 0x00000000000001e0 0x00000000000001e0  RW     0x8
  NOTE           0x00000000000002c4 0x00000000000002c4 0x00000000000002c4
                 0x0000000000000044 0x0000000000000044  R      0x4
  GNU_EH_FRAME   0x0000000000002004 0x0000000000002004 0x0000000000002004
                 0x0000000000000034 0x0000000000000034  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0x10
  GNU_RELRO      0x0000000000002de8 0x0000000000003de8 0x0000000000003de8
                 0x0000000000000218 0x0000000000000218  R      0x1

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
   03     .init .plt .text .fini
   04     .rodata .eh_frame_hdr .eh_frame
   05     .init_array .fini_array .dynamic .got .got.plt .data .bss
   06     .dynamic
   07     .note.ABI-tag .note.gnu.build-id
   08     .eh_frame_hdr
   09
   10     .init_array .fini_array .dynamic .got

如输出所示,文件中共有11个segment。只有类型为LOAD的段是运行时真正需要的。
除了段信息,还输出了每个段包含了哪些section。比如第二个LOAD段标志为R(只读)E(可执行)的,它的编号是03,表示它包含哪些section的那一行内容为:
03 .init .plt .text .fini
可以发现.text包含在其中,这一段就是代码段。
再比如第三个LOAD段,索引是04,标志为R(只读),但没有可执行的属性,它包含的section有.rodata .eh_frame_hdr .eh_frame,其中rodata表示只读的数据,也就是程序中用到的字符串常量等。
最后一个LOAD段,索引05,标志RW(可读写),它包含的节是.init_array .fini_array .dynamic .got .got.plt .data .bss,可以看到.data和.bss都包含其中,这段是数据段无疑。

今天先讲到这里,后面的内容这样组织:

  • 首先讲一下Elf文件的header,因为文件一开始几十个字节就是Elf header的数据,这个数据结构包含了很多信息,还能告诉我们program header table, section header table在文件中什么位置。
  • 接下来会讲一下如何解读section header table,以及section的数据如何组织的。
  • 然后会讲program header table,以及segment的数据组织。section是如何组织成段的,这一点我们也要弄请求。
  • 最后我们会讲程序如果被loader加载到内存中,生成进程映像的。

欢迎继续关注。

查看原文

Eason 赞了文章 · 2019-10-16

JavaScript数组去重(12种方法,史上最全)

数组去重,一般都是在面试的时候才会碰到,一般是要求手写数组去重方法的代码。如果是被提问到,数组去重的方法有哪些?你能答出其中的10种,面试官很有可能对你刮目相看。
在真实的项目中碰到的数组去重,一般都是后台去处理,很少让前端处理数组去重。虽然日常项目用到的概率比较低,但还是需要了解一下,以防面试的时候可能回被问到。

注:写的匆忙,加上这几天有点忙,还没有非常认真核对过,不过思路是没有问题,可能一些小细节出错而已。

数组去重的方法

一、利用ES6 Set去重(ES6中最常用)

function unique (arr) {
  return Array.from(new Set(arr))
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
 //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]

不考虑兼容性,这种去重的方法代码最少。这种方法还无法去掉“{}”空对象,后面的高阶方法会添加去掉重复“{}”的方法。

二、利用for嵌套for,然后splice去重(ES5中最常用)

function unique(arr){            
        for(var i=0; i<arr.length; i++){
            for(var j=i+1; j<arr.length; j++){
                if(arr[i]==arr[j]){         //第一个等同于第二个,splice方法删除第二个
                    arr.splice(j,1);
                    j--;
                }
            }
        }
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
    //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]     //NaN和{}没有去重,两个null直接消失了

双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。
想快速学习更多常用的ES6语法,可以看我之前的文章《学习ES6笔记──工作中常用到的ES6语法》

三、利用indexOf去重

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array = [];
    for (var i = 0; i < arr.length; i++) {
        if (array .indexOf(arr[i]) === -1) {
            array .push(arr[i])
        }
    }
    return array;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
   // [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}]  //NaN、{}没有去重

新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。

四、利用sort()

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return;
    }
    arr = arr.sort()
    var arrry= [arr[0]];
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] !== arr[i-1]) {
            arrry.push(arr[i]);
        }
    }
    return arrry;
}
     var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
// [0, 1, 15, "NaN", NaN, NaN, {…}, {…}, "a", false, null, true, "true", undefined]      //NaN、{}没有去重

利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。

五、利用对象的属性不能相同的特点进行去重(这种数组去重的方法有问题,不建议用,有待改进)

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var arrry= [];
     var  obj = {};
    for (var i = 0; i < arr.length; i++) {
        if (!obj[arr[i]]) {
            arrry.push(arr[i])
            obj[arr[i]] = 1
        } else {
            obj[arr[i]]++
        }
    }
    return arrry;
}
    var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
//[1, "true", 15, false, undefined, null, NaN, 0, "a", {…}]    //两个true直接去掉了,NaN和{}去重

六、利用includes

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array =[];
    for(var i = 0; i < arr.length; i++) {
            if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
                    array.push(arr[i]);
              }
    }
    return array
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
    //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]     //{}没有去重

七、利用hasOwnProperty

function unique(arr) {
    var obj = {};
    return arr.filter(function(item, index, arr){
        return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
    })
}
    var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}]   //所有的都去重了

利用hasOwnProperty 判断是否存在对象属性

八、利用filter

function unique(arr) {
  return arr.filter(function(item, index, arr) {
    //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
    return arr.indexOf(item, 0) === index;
  });
}
    var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]

九、利用递归去重

function unique(arr) {
        var array= arr;
        var len = array.length;

    array.sort(function(a,b){   //排序后更加方便去重
        return a - b;
    })

    function loop(index){
        if(index >= 1){
            if(array[index] === array[index-1]){
                array.splice(index,1);
            }
            loop(index - 1);    //递归loop,然后数组去重
        }
    }
    loop(len-1);
    return array;
}
 var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]

十、利用Map数据结构去重

function arrayNonRepeatfy(arr) {
  let map = new Map();
  let array = new Array();  // 数组用于返回结果
  for (let i = 0; i < arr.length; i++) {
    if(map .has(arr[i])) {  // 如果有该key值
      map .set(arr[i], true); 
    } else { 
      map .set(arr[i], false);   // 如果没有该key值
      array .push(arr[i]);
    }
  } 
  return array ;
}
 var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]

创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。

十一、利用reduce+includes

function unique(arr){
    return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]

十二、[...new Set(arr)]

[...new Set(arr)] 
//代码就是这么少----(其实,严格来说并不算是一种,相对于第一种方法来说只是简化了代码)

PS:有些文章提到了foreach+indexOf数组去重的方法,个人觉得都是大同小异,所以没有写上去。

查看原文

赞 586 收藏 452 评论 47

Eason 收藏了文章 · 2019-10-16

JavaScript数组去重(12种方法,史上最全)

数组去重,一般都是在面试的时候才会碰到,一般是要求手写数组去重方法的代码。如果是被提问到,数组去重的方法有哪些?你能答出其中的10种,面试官很有可能对你刮目相看。
在真实的项目中碰到的数组去重,一般都是后台去处理,很少让前端处理数组去重。虽然日常项目用到的概率比较低,但还是需要了解一下,以防面试的时候可能回被问到。

注:写的匆忙,加上这几天有点忙,还没有非常认真核对过,不过思路是没有问题,可能一些小细节出错而已。

数组去重的方法

一、利用ES6 Set去重(ES6中最常用)

function unique (arr) {
  return Array.from(new Set(arr))
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
 //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]

不考虑兼容性,这种去重的方法代码最少。这种方法还无法去掉“{}”空对象,后面的高阶方法会添加去掉重复“{}”的方法。

二、利用for嵌套for,然后splice去重(ES5中最常用)

function unique(arr){            
        for(var i=0; i<arr.length; i++){
            for(var j=i+1; j<arr.length; j++){
                if(arr[i]==arr[j]){         //第一个等同于第二个,splice方法删除第二个
                    arr.splice(j,1);
                    j--;
                }
            }
        }
return arr;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
    //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}]     //NaN和{}没有去重,两个null直接消失了

双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。
想快速学习更多常用的ES6语法,可以看我之前的文章《学习ES6笔记──工作中常用到的ES6语法》

三、利用indexOf去重

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array = [];
    for (var i = 0; i < arr.length; i++) {
        if (array .indexOf(arr[i]) === -1) {
            array .push(arr[i])
        }
    }
    return array;
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
   // [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}]  //NaN、{}没有去重

新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。

四、利用sort()

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return;
    }
    arr = arr.sort()
    var arrry= [arr[0]];
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] !== arr[i-1]) {
            arrry.push(arr[i]);
        }
    }
    return arrry;
}
     var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
// [0, 1, 15, "NaN", NaN, NaN, {…}, {…}, "a", false, null, true, "true", undefined]      //NaN、{}没有去重

利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。

五、利用对象的属性不能相同的特点进行去重(这种数组去重的方法有问题,不建议用,有待改进)

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var arrry= [];
     var  obj = {};
    for (var i = 0; i < arr.length; i++) {
        if (!obj[arr[i]]) {
            arrry.push(arr[i])
            obj[arr[i]] = 1
        } else {
            obj[arr[i]]++
        }
    }
    return arrry;
}
    var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
//[1, "true", 15, false, undefined, null, NaN, 0, "a", {…}]    //两个true直接去掉了,NaN和{}去重

六、利用includes

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array =[];
    for(var i = 0; i < arr.length; i++) {
            if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
                    array.push(arr[i]);
              }
    }
    return array
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
    //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]     //{}没有去重

七、利用hasOwnProperty

function unique(arr) {
    var obj = {};
    return arr.filter(function(item, index, arr){
        return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
    })
}
    var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}]   //所有的都去重了

利用hasOwnProperty 判断是否存在对象属性

八、利用filter

function unique(arr) {
  return arr.filter(function(item, index, arr) {
    //当前元素,在原始数组中的第一个索引==当前索引值,否则返回当前元素
    return arr.indexOf(item, 0) === index;
  });
}
    var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
        console.log(unique(arr))
//[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]

九、利用递归去重

function unique(arr) {
        var array= arr;
        var len = array.length;

    array.sort(function(a,b){   //排序后更加方便去重
        return a - b;
    })

    function loop(index){
        if(index >= 1){
            if(array[index] === array[index-1]){
                array.splice(index,1);
            }
            loop(index - 1);    //递归loop,然后数组去重
        }
    }
    loop(len-1);
    return array;
}
 var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr))
//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]

十、利用Map数据结构去重

function arrayNonRepeatfy(arr) {
  let map = new Map();
  let array = new Array();  // 数组用于返回结果
  for (let i = 0; i < arr.length; i++) {
    if(map .has(arr[i])) {  // 如果有该key值
      map .set(arr[i], true); 
    } else { 
      map .set(arr[i], false);   // 如果没有该key值
      array .push(arr[i]);
    }
  } 
  return array ;
}
 var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
    console.log(unique(arr))
//[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined]

创建一个空Map数据结构,遍历需要去重的数组,把数组的每一个元素作为key存到Map中。由于Map中不会出现相同的key值,所以最终得到的就是去重后的结果。

十一、利用reduce+includes

function unique(arr){
    return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}
var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}];
console.log(unique(arr));
// [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]

十二、[...new Set(arr)]

[...new Set(arr)] 
//代码就是这么少----(其实,严格来说并不算是一种,相对于第一种方法来说只是简化了代码)

PS:有些文章提到了foreach+indexOf数组去重的方法,个人觉得都是大同小异,所以没有写上去。

查看原文

Eason 赞了问题 · 2019-10-14

mysql如何提高视图查询速度?

最近数据库从5.5.18升级到了5.6.38,出现了一个问题,有个视图同样的数据量执行效率相比老数据库慢了20倍,应该怎么优化?

如下是视图sql:

SELECT
    `wz_demand`.`id` AS `id`,
    `wz_demand`.`operator` AS `operator`,
    `wz_member`.`username` AS `musername`,
    `wz_admin`.`truename` AS `truename`,
    `wz_demand`.`cid` AS `cid`,
    `wz_demand`.`title` AS `title`,
    `wz_demand`.`css` AS `css`,
    `wz_demand`.`thumb` AS `thumb`,
    `wz_demand`.`keywords` AS `keywords`,
    `wz_demand`.`remark` AS `remark`,
    `wz_demand`.`url` AS `url`,
    `wz_demand`.`status` AS `status`,
    `wz_demand`.`route` AS `route`,
    `wz_demand`.`publisher` AS `publisher`,
    `wz_demand`.`addtime` AS `addtime`,
    `wz_demand`.`updatetime` AS `updatetime`,
    `wz_demand`.`coin` AS `coin`,
    `wz_demand`.`template` AS `template`,
    `wz_demand`.`areaid` AS `areaid`,
    `wz_demand`.`areaid_1` AS `areaid_1`,
    `wz_demand`.`areaid_2` AS `areaid_2`,
    `wz_demand`.`sort` AS `sort`,
    `wz_demand`.`telephone` AS `telephone`,
    `wz_demand`.`address` AS `address`,
    `wz_demand`.`housecategory` AS `housecategory`,
    `wz_demand`.`renovation` AS `renovation`,
    `wz_demand`.`renovationcategory` AS `renovationcategory`,
    `wz_demand`.`housetype` AS `housetype`,
    `wz_demand`.`style` AS `style`,
    `wz_demand`.`area` AS `area`,
    `wz_demand`.`way` AS `way`,
    `wz_demand`.`budget` AS `budget`,
    `wz_demand`.`iscompany` AS `iscompany`,
    `wz_demand`.`leadtime` AS `leadtime`,
    `wz_demand`.`decorationtime` AS `decorationtime`,
    `wz_demand`.`source` AS `source`,
    `wz_demand`.`homestyle` AS `homestyle`,
    `wz_demand`.`content` AS `content`,
    `wz_demand`.`progress` AS `progress`,
    `wz_demand`.`progress1time` AS `progress1time`,
    `wz_demand`.`progress2time` AS `progress2time`,
    `wz_demand`.`progress3time` AS `progress3time`,
    `wz_demand`.`progress4time` AS `progress4time`,
    `wz_demand`.`order_no` AS `order_no`,
    `wz_demand`.`wait_comment` AS `wait_comment`,
    `wz_demand`.`referer` AS `referer`,
    `wz_demand`.`yxgsm` AS `yxgsm`,
    `wz_demand`.`orderplan` AS `orderplan`,
    `wz_demand`.`ispay` AS `ispay`,
    `wz_demand`.`uid` AS `uid`,
    `wz_demand`.`mobile` AS `mobile`,
    `wz_demand`.`sflf` AS `sflf`,
    `wz_demand`.`managerid` AS `managerid`,
    `wz_demand`.`managername` AS `managername`,
    `wz_demand`.`housekeeperid` AS `housekeeperid`,
    `wz_demand`.`housekeeper` AS `housekeeper`,
    `wz_demand`.`paystatus` AS `paystatus`,
    `wz_demand`.`orderstatus` AS `orderstatus`,
    `wz_demand`.`orderstep` AS `orderstep`,
    `wz_demand`.`nodeid` AS `nodeid`,
    `wz_demand`.`nodename` AS `nodename`,
    `wz_demand`.`outpaystaus` AS `outpaystaus`,
    `wz_demand`.`tj_name` AS `tj_name`,
    `wz_demand`.`designpay` AS `designpay`,
    `wz_demand`.`totalpay` AS `totalpay`,
    `wz_demand`.`designno` AS `designno`,
    `wz_demand`.`contactno` AS `contactno`,
    `wz_demand`.`extrapay` AS `extrapay`,
    `wz_demand`.`payforcompanystatus` AS `payforcompanystatus`,
    `wz_demand`.`ysclsd` AS `ysclsd`,
    `wz_demand`.`ysnm` AS `ysnm`,
    `wz_demand`.`ysclyq` AS `ysclyq`,
    `wz_demand`.`yssd` AS `yssd`,
    `wz_demand`.`ysclnm` AS `ysclnm`,
    `wz_demand`.`sdys` AS `sdys`,
    `wz_demand`.`paystype` AS `paystype`,
    `wz_demand`.`sign` AS `sign`,
    `wz_demand`.`getdate` AS `getdate`,
    `wz_demand`.`seriesnumber` AS `seriesnumber`,
    `wz_demand`.`logname` AS `logname`,
    `wz_demand`.`tj_tel` AS `tj_tel`,
    `wz_demand`.`domain` AS `domain`,
    `wz_demand`.`bao` AS `bao`,
    `wz_demand`.`ysyq` AS `ysyq`,
    `wz_demand`.`wrzl` AS `wrzl`,
    `wz_demand`.`kqzl` AS `kqzl`,
    `wz_demand`.`username` AS `username`,
    `wz_demand`.`applytype` AS `applytype`,
    `wz_demand`.`isApply` AS `isApply`,
    `wz_demand`.`name` AS `name`,
    `wz_demand`.`referrals` AS `referrals`,
    `wz_demand`.`referral` AS `referral`,
    `wz_demand`.`community` AS `community`,
    `wz_demand`.`companyname` AS `companyname`,
    `wz_demand`.`collection` AS `collection`,
    `wz_demand`.`three_no` AS `three_no`,
    `wz_demand`.`order_source` AS `order_source`,
    `wz_demand`.`wait_hf` AS `wait_hf`,
    `wz_demand`.`other` AS `other`,
    `wz_member`.`uid` AS `muid`,
    `wz_admin`.`uid` AS `auid`,
    `wz_demand`.`kfzy` AS `kfzy` 
FROM
    (
        (
            `wz_demand`
            LEFT JOIN `wz_member` ON ( ( `wz_demand`.`operator` = `wz_member`.`username` ) ) 
        )
    LEFT JOIN `wz_admin` ON ( ( `wz_member`.`uid` = `wz_admin`.`uid` ) ) 
    )

这里是5.6版本执行时间和explain结果:
图片描述

clipboard.png

这里是5.5版本执行时间和explain结果:
clipboard.png
clipboard.png

关注 6 回答 1

Eason 收藏了问题 · 2019-10-14

mysql如何提高视图查询速度?

最近数据库从5.5.18升级到了5.6.38,出现了一个问题,有个视图同样的数据量执行效率相比老数据库慢了20倍,应该怎么优化?

如下是视图sql:

SELECT
    `wz_demand`.`id` AS `id`,
    `wz_demand`.`operator` AS `operator`,
    `wz_member`.`username` AS `musername`,
    `wz_admin`.`truename` AS `truename`,
    `wz_demand`.`cid` AS `cid`,
    `wz_demand`.`title` AS `title`,
    `wz_demand`.`css` AS `css`,
    `wz_demand`.`thumb` AS `thumb`,
    `wz_demand`.`keywords` AS `keywords`,
    `wz_demand`.`remark` AS `remark`,
    `wz_demand`.`url` AS `url`,
    `wz_demand`.`status` AS `status`,
    `wz_demand`.`route` AS `route`,
    `wz_demand`.`publisher` AS `publisher`,
    `wz_demand`.`addtime` AS `addtime`,
    `wz_demand`.`updatetime` AS `updatetime`,
    `wz_demand`.`coin` AS `coin`,
    `wz_demand`.`template` AS `template`,
    `wz_demand`.`areaid` AS `areaid`,
    `wz_demand`.`areaid_1` AS `areaid_1`,
    `wz_demand`.`areaid_2` AS `areaid_2`,
    `wz_demand`.`sort` AS `sort`,
    `wz_demand`.`telephone` AS `telephone`,
    `wz_demand`.`address` AS `address`,
    `wz_demand`.`housecategory` AS `housecategory`,
    `wz_demand`.`renovation` AS `renovation`,
    `wz_demand`.`renovationcategory` AS `renovationcategory`,
    `wz_demand`.`housetype` AS `housetype`,
    `wz_demand`.`style` AS `style`,
    `wz_demand`.`area` AS `area`,
    `wz_demand`.`way` AS `way`,
    `wz_demand`.`budget` AS `budget`,
    `wz_demand`.`iscompany` AS `iscompany`,
    `wz_demand`.`leadtime` AS `leadtime`,
    `wz_demand`.`decorationtime` AS `decorationtime`,
    `wz_demand`.`source` AS `source`,
    `wz_demand`.`homestyle` AS `homestyle`,
    `wz_demand`.`content` AS `content`,
    `wz_demand`.`progress` AS `progress`,
    `wz_demand`.`progress1time` AS `progress1time`,
    `wz_demand`.`progress2time` AS `progress2time`,
    `wz_demand`.`progress3time` AS `progress3time`,
    `wz_demand`.`progress4time` AS `progress4time`,
    `wz_demand`.`order_no` AS `order_no`,
    `wz_demand`.`wait_comment` AS `wait_comment`,
    `wz_demand`.`referer` AS `referer`,
    `wz_demand`.`yxgsm` AS `yxgsm`,
    `wz_demand`.`orderplan` AS `orderplan`,
    `wz_demand`.`ispay` AS `ispay`,
    `wz_demand`.`uid` AS `uid`,
    `wz_demand`.`mobile` AS `mobile`,
    `wz_demand`.`sflf` AS `sflf`,
    `wz_demand`.`managerid` AS `managerid`,
    `wz_demand`.`managername` AS `managername`,
    `wz_demand`.`housekeeperid` AS `housekeeperid`,
    `wz_demand`.`housekeeper` AS `housekeeper`,
    `wz_demand`.`paystatus` AS `paystatus`,
    `wz_demand`.`orderstatus` AS `orderstatus`,
    `wz_demand`.`orderstep` AS `orderstep`,
    `wz_demand`.`nodeid` AS `nodeid`,
    `wz_demand`.`nodename` AS `nodename`,
    `wz_demand`.`outpaystaus` AS `outpaystaus`,
    `wz_demand`.`tj_name` AS `tj_name`,
    `wz_demand`.`designpay` AS `designpay`,
    `wz_demand`.`totalpay` AS `totalpay`,
    `wz_demand`.`designno` AS `designno`,
    `wz_demand`.`contactno` AS `contactno`,
    `wz_demand`.`extrapay` AS `extrapay`,
    `wz_demand`.`payforcompanystatus` AS `payforcompanystatus`,
    `wz_demand`.`ysclsd` AS `ysclsd`,
    `wz_demand`.`ysnm` AS `ysnm`,
    `wz_demand`.`ysclyq` AS `ysclyq`,
    `wz_demand`.`yssd` AS `yssd`,
    `wz_demand`.`ysclnm` AS `ysclnm`,
    `wz_demand`.`sdys` AS `sdys`,
    `wz_demand`.`paystype` AS `paystype`,
    `wz_demand`.`sign` AS `sign`,
    `wz_demand`.`getdate` AS `getdate`,
    `wz_demand`.`seriesnumber` AS `seriesnumber`,
    `wz_demand`.`logname` AS `logname`,
    `wz_demand`.`tj_tel` AS `tj_tel`,
    `wz_demand`.`domain` AS `domain`,
    `wz_demand`.`bao` AS `bao`,
    `wz_demand`.`ysyq` AS `ysyq`,
    `wz_demand`.`wrzl` AS `wrzl`,
    `wz_demand`.`kqzl` AS `kqzl`,
    `wz_demand`.`username` AS `username`,
    `wz_demand`.`applytype` AS `applytype`,
    `wz_demand`.`isApply` AS `isApply`,
    `wz_demand`.`name` AS `name`,
    `wz_demand`.`referrals` AS `referrals`,
    `wz_demand`.`referral` AS `referral`,
    `wz_demand`.`community` AS `community`,
    `wz_demand`.`companyname` AS `companyname`,
    `wz_demand`.`collection` AS `collection`,
    `wz_demand`.`three_no` AS `three_no`,
    `wz_demand`.`order_source` AS `order_source`,
    `wz_demand`.`wait_hf` AS `wait_hf`,
    `wz_demand`.`other` AS `other`,
    `wz_member`.`uid` AS `muid`,
    `wz_admin`.`uid` AS `auid`,
    `wz_demand`.`kfzy` AS `kfzy` 
FROM
    (
        (
            `wz_demand`
            LEFT JOIN `wz_member` ON ( ( `wz_demand`.`operator` = `wz_member`.`username` ) ) 
        )
    LEFT JOIN `wz_admin` ON ( ( `wz_member`.`uid` = `wz_admin`.`uid` ) ) 
    )

这里是5.6版本执行时间和explain结果:
图片描述

clipboard.png

这里是5.5版本执行时间和explain结果:
clipboard.png
clipboard.png

Eason 赞了回答 · 2019-09-21

解决iterm 配置utf8编码,本地终端中文不乱码,ssh远程中文乱码,咋整啊

问题:

服务器是ubuntu,用Mac的iterm2 ssh连上去,终端显示中文乱码,也不能输入中文,然而本地终端可以显示和输入。

解决方法:

这种情况一般是终端和服务器的字符集不匹配,MacOSX下默认的是utf8字符集。
输入locale可以查看字符编码设置情况,而我的对应值是空的。
因为我在本地和服务器都用zsh替代了bash,而且使用了oh-my-zsh,而默认的.zshrc没有设置为utf-8编码,所以本地和服务器端都要在.zshrc设置,步骤如下,bash对应.bash_profile.bashrc文件。

1.在终端下输入

vim ~/.zshrc

或者使用其他你喜欢的编辑器编辑~/.zshrc文件
<!--more-->

2.在文件内容末端添加:

export LC_ALL=en_US.UTF-8  
export LANG=en_US.UTF-8

接着重启一下终端,或者输入source ~/.zshrc使设置生效。

设置成功的话,在本地和登录到服务器输入locale回车会显示下面内容。

LANG="en_US.UTF-8"
LC_COLLATE="en_US.UTF-8"
LC_CTYPE="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_MONETARY="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_ALL="en_US.UTF-8"

这时,中文输入和显示都正常了。

关注 9 回答 4

Eason 收藏了问题 · 2019-09-20

Mac 更改/usr/bin 目录权限失败

在Mac系统下用如下命令更改用户权限结果失败
sudo chmod -R 777 bin
提示我 Operation not permitted,切换为root账户更改该目录权限还是提示Operation not permitted, 系统版本:10.11 Beta (15A243d)

认证与成就

  • 获得 10 次点赞
  • 获得 52 枚徽章 获得 1 枚金徽章, 获得 14 枚银徽章, 获得 37 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2016-10-17
个人主页被 1.4k 人浏览