Compare Arrays in JavaScript

HarmonyOS NEXT 系统推荐使用 Lodash 库,更符合开发直觉。

ohpm install lodash

Arrays are objects in JavaScript, so the triple equals operator === only returns true if the arrays are the same reference.

const a = [1, 2, 3];
const b = [1, 2, 3];

a === a; // true
a === b; // false

How do you compare whether two arrays are equal? Equality is a tricky subject: the JavaScript spec defines 4 different ways of checking if two values are "equal", and that doesn't take into account deep equality between objects.

In cases like this, it helps to be as explicit as possible about what you mean by "equal." In software engineering, asking a question in the right way often makes the answer obvious.

With that in mind, here's 3 definitions of equality for arrays and how to check them.

Same Length, Each Value Equal

One approach for comparing a and b is checking if each value of a is strictly equal to the corresponding value of b. This works well if all the elements of the arrays are primitives as opposed to objects.

const a = [1, 2, 3];
const b = [4, 5, 6];
const c = [1, 2, 3];

function arrayEquals(a, b) {
  return Array.isArray(a) &&
    Array.isArray(b) &&
    a.length === b.length &&
    a.every((val, index) => val === b[index]);
}

arrayEquals(a, b); // false
arrayEquals(a, c); // true

Deep Equality With POJOs

The previous arrayEquals() function works great for primitive values, but falls short if you want to compare objects by value.

const a = [{ answer: 42 }, { powerLevel: 9001 }];
const b = [{ answer: 42 }, { powerLevel: 9001 }];

// false, because { answer: 42 } !== { answer: 42 }, different references
arrayEquals(a, b);

One neat way to take into account object values is comparing arrays by their JSON.stringify() output.

const a = [{ answer: 42 }, { powerLevel: 9001 }];
const b = [{ answer: 42 }, { powerLevel: 9001 }];
const c = [{ answer: 42 }, { password: 'taco' }];

JSON.stringify(a) === JSON.stringify(b); // true
JSON.stringify(a) === JSON.stringify(c); // false

This approach is handy because it requires minimal code and no outside libraries. However, comparing JSON.stringify() output has an unfortunate edge case that may be a problem depending on your use case. Since undefined isn't a valid JSON value, the below arrays have the same JSON.stringify() output, because JSON.stringify() converts undefined to null.

const a = [undefined];
const b = [null];

Using Lodash's isEqual()

In addition to the null vs undefined quirk, comparing JSON.stringify() output also doesn't take into account object types. As far as JSON.stringify() is concerned, an object with a toJSON() function that returns 42 is the same as the number 42.

const a = [{ toJSON: () => 42 }];
const b = [42];

JSON.stringify(a); // '[42]'
JSON.stringify(b); // '[42]'

Similarly, a custom object is the same as a POJO:

class MyClass {
  constructor(obj) {
    Object.assign(this, obj);
  }
}

const a = [new MyClass({ answer: 42 })];
const b = [{ answer: 42 }];

JSON.stringify(a) === JSON.stringify(b); // true

Lodash's isEqual() function, on the other hand, takes all this into account.

const _ = require('lodash');

class MyClass {
  constructor(obj) {
    Object.assign(this, obj);
  }
}

const a = [new MyClass({ answer: 42 })];
const b = [{ answer: 42 }];

_.isEqual(a, b); // false

Lodash's isEqual() function is the way to go if you need all the bells and whistles of checking that objects have the same class. The JSON.stringify() approach works well for POJOs, just make sure you take into account null and only use it with trusted data - toJSON() can be a security vulnerability.

参考链接


Compare Arrays in JavaScript

make: *** No rule to make target `sqlite_cfg.h', needed by `.target_source'

前置条件

  • macOS Sonoma (14.4.1) 
  • MacBook Pro 2023-Apple M2 Pro (4能效核、8性能核、32GB内存、2TB磁盘)
  • Homebrew (4.2.18 或更高版本)
  • Xcode Version 15.3 (15E204a)
  • DevEco Studio NEXT Developer Preview2 4.1.3.700

错误信息

源代码编译 sqlite3

# https://github.com/clemensg/sqlite3pod
$ wget https://www.sqlite.org/2024/sqlite-src-3450100.zip

$ unzip sqlite-src-3450100.zip

$ cd sqlite-src-3450100

$ ./configure

$ make

或者使用 pod 安装 sqlite3 报错:

$ pod try sqlite3
Updating spec repositories

Trying sqlite3
[!] /opt/homebrew/bin/bash -c 
set -e
cd sqlite-src-3450100
./configure
make sqlite3.c sqlite3.h sqlite3ext.h

checking build system type... arm-apple-darwin23.4.0
checking host system type... arm-apple-darwin23.4.0
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking for a sed that does not truncate output... /opt/homebrew/bin/gsed
checking for grep that handles long lines and -e... /opt/homebrew/bin/ggrep
checking for egrep... /opt/homebrew/bin/ggrep -E
checking for fgrep... /opt/homebrew/bin/ggrep -F
checking for ld used by gcc... /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld
checking if the linker (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld) is GNU ld... no
checking for BSD- or MS-compatible name lister (nm)... /usr/bin/nm -B
checking the name lister (/usr/bin/nm -B) interface... BSD nm
checking whether ln -s works... yes
checking the maximum length of command line arguments... 786432
checking whether the shell understands some XSI constructs... yes
checking whether the shell understands "+="... yes
checking for /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld option to reload object files... -r
checking for objdump... objdump
checking how to recognize dependent libraries... pass_all
checking for ar... ar
checking for strip... strip
checking for ranlib... ranlib
checking command to parse /usr/bin/nm -B output from gcc object... ok
checking for dsymutil... dsymutil
checking for nmedit... nmedit
checking for lipo... lipo
checking for otool... otool
checking for otool64... no
checking for -single_module linker flag... no
checking for -exported_symbols_list linker flag... yes
checking how to run the C preprocessor... gcc -E
checking for ANSI C header files... yes
checking for sys/types.h... yes
checking for sys/stat.h... yes
checking for stdlib.h... yes
checking for string.h... yes
checking for memory.h... yes
checking for strings.h... yes
checking for inttypes.h... yes
checking for stdint.h... yes
checking for unistd.h... yes
checking for dlfcn.h... yes
checking for objdir... .libs
checking if gcc supports -fno-rtti -fno-exceptions... yes
checking for gcc option to produce PIC... -fno-common -DPIC
checking if gcc PIC flag -fno-common -DPIC works... yes
checking if gcc static flag -static works... no
checking if gcc supports -c -o file.o... yes
checking if gcc supports -c -o file.o... (cached) yes
checking whether the gcc linker (/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld) supports shared libraries... yes
checking dynamic linker characteristics... darwin23.4.0 dyld
checking how to hardcode library paths into programs... immediate
checking whether stripping libraries is possible... yes
checking if libtool supports shared libraries... yes
checking whether to build shared libraries... yes
checking whether to build static libraries... yes
checking for a BSD-compatible install... /opt/homebrew/bin/ginstall -c
checking for special C compiler options needed for large files... no
checking for _FILE_OFFSET_BITS value needed for large files... no
checking for int8_t... yes
checking for int16_t... yes
checking for int32_t... yes
checking for int64_t... yes
checking for intptr_t... yes
checking for uint8_t... yes
checking for uint16_t... yes
checking for uint32_t... yes
checking for uint64_t... yes
checking for uintptr_t... yes
checking for sys/types.h... (cached) yes
checking for stdlib.h... (cached) yes
checking for stdint.h... (cached) yes
checking for inttypes.h... (cached) yes
checking malloc.h usability... no
checking malloc.h presence... no
checking for malloc.h... no
checking for fdatasync... yes
checking for gmtime_r... yes
checking for isnan... yes
checking for localtime_r... yes
checking for localtime_s... no
checking for malloc_usable_size... no
checking for strchrnul... no
checking for usleep... yes
checking for utime... yes
checking for pread... yes
checking for pread64... no
checking for pwrite... yes
checking for pwrite64... no
checking for tclsh8.7... no
checking for tclsh8.6... tclsh8.6
configure: Version set to 3.45
configure: Release set to 3.45.1
checking for WASI SDK directory... no
checking whether to support threadsafe operation... yes
checking for library containing pthread_create... none required
checking for library containing pthread_mutexattr_init... none required
checking whether to support shared library linked as release mode or not... no
checking whether to use an in-ram database for temporary tables... no
checking if executables have the .exe suffix... unknown
checking for Tcl configuration... found /opt/homebrew/Cellar/tcl-tk/8.6.14/lib/tclConfig.sh
checking for existence of /opt/homebrew/Cellar/tcl-tk/8.6.14/lib/tclConfig.sh... loading
checking for library containing readline... -ledit
not using linenoise
checking for library containing fdatasync... none required
checking build type... release
checking zlib.h usability... yes
checking zlib.h presence... yes
checking for zlib.h... yes
checking for library containing deflate... -lz
checking for library containing dlopen... none required
checking whether to support math functions... yes
checking for library containing ceil... none required
checking whether to support JSON functions... yes
checking whether to support MEMSYS5... no
checking whether to support MEMSYS3... no
checking whether to support FTS3... no
checking whether to support FTS4... no
checking whether to support FTS5... no
checking whether to support LIMIT on UPDATE and DELETE statements... no
checking whether to support GEOPOLY... no
checking whether to support RTREE... no
checking whether to support SESSION... no
configure: creating ./config.status
config.status: creating Makefile
config.status: creating sqlite3.pc
config.status: creating sqlite_cfg.h
config.status: sqlite_cfg.h is unchanged
config.status: executing libtool commands
gcc  -g -O2 -o mkkeywordhash -DSQLITE_ENABLE_MATH_FUNCTIONS  /private/var/folders/z8/_cvsdvbd4x51vm4szw5xkw0w0000gn/T/CocoaPods/Try/sqlite3/sqlite-src-3450100/tool/mkkeywordhash.c
./mkkeywordhash >keywordhash.h
gcc  -g -O2 -o lemon /private/var/folders/z8/_cvsdvbd4x51vm4szw5xkw0w0000gn/T/CocoaPods/Try/sqlite3/sqlite-src-3450100/tool/lemon.c
cp /private/var/folders/z8/_cvsdvbd4x51vm4szw5xkw0w0000gn/T/CocoaPods/Try/sqlite3/sqlite-src-3450100/tool/lempar.c .
cp /private/var/folders/z8/_cvsdvbd4x51vm4szw5xkw0w0000gn/T/CocoaPods/Try/sqlite3/sqlite-src-3450100/src/parse.y .
./lemon -DSQLITE_ENABLE_MATH_FUNCTIONS  -S parse.y
sh /private/var/folders/z8/_cvsdvbd4x51vm4szw5xkw0w0000gn/T/CocoaPods/Try/sqlite3/sqlite-src-3450100/tool/cktclsh.sh 8.4 tclsh8.6
touch has_tclsh84
cat parse.h /private/var/folders/z8/_cvsdvbd4x51vm4szw5xkw0w0000gn/T/CocoaPods/Try/sqlite3/sqlite-src-3450100/src/vdbe.c | tclsh8.6 /private/var/folders/z8/_cvsdvbd4x51vm4szw5xkw0w0000gn/T/CocoaPods/Try/sqlite3/sqlite-src-3450100/tool/mkopcodeh.tcl >opcodes.h
tclsh8.6 /private/var/folders/z8/_cvsdvbd4x51vm4szw5xkw0w0000gn/T/CocoaPods/Try/sqlite3/sqlite-src-3450100/tool/mkopcodec.tcl opcodes.h >opcodes.c
make: *** No rule to make target `sqlite_cfg.h', needed by `.target_source'.  Stop.

观察源代码目录,也确实没有 sqlite_cfg.h 文件生成。

继续阅读make: *** No rule to make target `sqlite_cfg.h', needed by `.target_source'

Flutter: Xcode error “Unable to boot the Simulator“

使用 flutter、Android Studio ,通过iOS模拟器运行项目,一直一切正常。

某次重启后无法启动模拟器,报错信息如下:

 "Unable to boot the simulator".

解决方法,亲测有效:

macOS 14.4.1以及更高版本:
进入 “系统设置”→“通用”→“存储空间”→“开发者” 删除 “XCode 缓存” 。

在 macOS 13 及更高版本上:
进入 “系统设置”→“常规”→“存储”→“开发人员”
删除“开发者缓存”

在 macOS 12 及更低版本上:
转到“关于本机”→“存储”→“管理”→“开发人员”

参考链接


Flutter: XCode error “Unable to boot the Simulator