我想将
string[][]
压扁为 string[]
。
数十个SO答案中给出的建议是:
[].concat(...arrays)
。
但这给了我这个错误:
“string[]”类型的参数不可分配给“ConcatArray”类型的参数。
属性“切片”的类型不兼容。
类型 '(start?: number | undefined, end?: number | undefined) => string[]' 不可分配给类型 '(start?: number | undefined, end?: number | undefined) => never[]' .
类型“string[]”不可分配给类型“never[]”。
类型“string”不可分配给类型“never”。
我尝试的另一种方法是:
let foo: string[][] = [["a", "b", "c"], ["a", "b", "c"], ["a", "b", "c"]];
let bar = [].concat(...foo);
这给出了类似的错误:
“string[]”类型的参数不可分配给“ConcatArray”类型的参数。
为什么它对除了我以外的所有人都有效?
试试这个:
const a = [["a", "b", "c"], ["a", "b", "c"], ["a", "b", "c"]]
const result = a.reduce((accumulator, value) => accumulator.concat(value), []);
console.log(result)
您可以使用
flat()
展平数组
let foo: string[][] = [["a", "b", "c"], ["a", "b", "c"], ["a", "b", "c"]];
let bar = foo.flat()
日志
console.log(bar) // a,b,c,a,b,c,a,b,c
更新
通过将类型更正为 string[],您还可以使用
concat
let foo: string[][] = [["a", "b", "c"], ["a", "b", "c"], ["a", "b", "c"]];
let bar : string[] = []
bar = bar.concat(foo[0], foo[1], foo[2])
这是最简单的选择:
let bar = ([] as string[]).concat(...foo);
类似于@Kokodoko 的方法,但输入是内联的。
这是一个通用解决方案:
function flatten<T>(arr: T[][]): T[] {
return ([] as T[]).concat(...arr);
}
以及深度/递归扩展:
type NestedArray<T> = Array<NestedArray<T> | T>;
function flattenDeep<T>(input: NestedArray<T>): T[] {
return flatten(input.map(x => Array.isArray(x) ? flattenDeep(x) : [x]));
};
这个答案对于深度扁平化可能更有效,我只是很高兴尝试写一些对我来说更优雅的东西。
.flat() 也会给出类型错误。 您可以使用泛型来解决这个问题
let st : string[][] | Array<string> = [['a'] , ['b']]
let bar = [].concat(...st);
console.log(bar)
无论哪种方式,你的决定。只需知道您的类型声明不正确即可。
代码
const res = [].concat(...foo);
应该可以。我猜这是 tsconfig 中的错误配置导致了您的错误。确保 tsconfig 的
es2015
数组中至少有 es2018
(更好的 lib
)。要使新的 flat
正常工作,如 kokodoko 所示,请确保还添加 esnext
"lib": [
"es2018",
"dom",
"esnext"
]
我相信你有 strictNullCheck: true
没有上下文类型的空数组([].concat(arg) 中的 [])在 strictNullChecks 下被推断为 never[]。并且 never 不能从任何其他类型分配。
([] as any[]).concat(foo);应该可以解决问题
对于更深层嵌套的数组,例如:
[1, 2, 3, [4, [5, [6, [7]]]]]
type NestedArray<T> = Array<NestedArray<T> | T>;
const flatten = <T>(input: NestedArray<T>, acc: T[] = []): T[] => {
return input.reduce((_: T[], current) => {
if (Array.isArray(current)) return flatten(current, acc);
acc.push(current);
return acc;
}, []);
};
用途:
console.log(flatten([1, 2, 3, [4, [5, [6, [7]]]]]));
来自Steven的答案适用于我的玩笑测试,但由于我无法弄清楚的约束错误,不适用于我实际的 Angular 15 应用程序。稍微修改为常规递归函数以保持 Typescript 安静:
import { Injectable} from '@angular/core';
export type NestedArray<T> = Array<NestedArray<T> | T>;
export class ArrayHelper {
public static flatten = <T>(input: NestedArray<T>, res: T[] = []): T[] => {
input.forEach((el: T | NestedArray<T>) => {
if (Array.isArray(el)) {
ArrayHelper.flatten(el, res);
} else {
res.push(el);
}
});
return res;
};
}
测试示例:
describe('flattening', () => {
it('pass through', () => {
expect(ArrayHelper.flatten(['hi', 'there'])).toHaveLength(2);
});
it('2 level', () => {
expect(ArrayHelper.flatten(['hi', 'there', ['that', 'is', 'all', 'folks']])).toHaveLength(6);
});
it('as per SO', () => {
expect(ArrayHelper.flatten([1, 2, 3, [4, [5, [6, [7]]]]])).toHaveLength(7);
});
});
var foo = [["a", "b", "c"], ["a", "b", "c"], ["a", "b", "c"],[['x','y','z']]];
var bar = foo.flat(Infinity)
console.log(bar)
信息:带有参数 Infinity 的 Array.Flat 意味着将其展平,直到不存在嵌套数组。