我有一个用例,我需要使用字符串来匹配对象值
例如
'one': {
'two': {
'three': 'val'
}
}
}
split
和reduce
似乎是解决此问题的方法,但是我还没有使用下面的代码使它起作用
const string = 'one.two.three';
const test = string
.split('.')
.reduce((obj, key) => {
return obj[key]
});
console.log(test);
//expected one['two']['three']
[编辑以添加更多上下文] 我有一个HTML模板(角度7),它调用了sort函数
(click)="sortColumn('spn.subscriptionId')"
我有以下对象来跟踪每一列的排序顺序
public sortableColumns = [
{ colName: 'name', colSortDir: 'none'},
{ colName: 'spn.subId', colSortDir: 'none'},
{ colName: 'regionName', colSortDir: 'none'},
{ colName: 'customerName', colSortDir: 'none'}
];
和sortColumn
函数。 this.subscriptions
来自rest api。如果存在一个剩余的api对象只有一个级别-'name',但不适用于嵌套对象-spn.subscriptionId
public sortColumn(column : string) {
// resets other columns
this.sortableColumns.forEach((el) => {
if (el.colName !== column) {
el.colSortDir = 'none';
}
});
// matches the column name passed with sortableColumns to set order in UI
const col = this.sortableColumns.filter((el) => {
return el.colName === column;
});
// sorting of the array object. this.subscriptions comes fr
if (col[0].colSortDir === 'asc') {
col[0].colSortDir = 'dsc';
this.subscriptions.sort((val1, val2) => {
if (val1[column] < val2[column]) {
return -1;
} else if (val1[column] > val2[column]) {
return 1;
} else {
return 0;
}
});
} else if (col[0].colSortDir === 'none' || col[0].colSortDir === 'dsc') {
col[0].colSortDir = 'asc';
this.subscriptions.sort((val1, val2) => {
if (val1[column] > val2[column]) {
return -1;
} else if (val1[column] < val2[column]) {
return 1;
} else {
return 0;
}
});
}
}
答案 0 :(得分:1)
没有神奇的“查找键”,您可以将其插入括号表示法obj[key]
中并使其遍历多个嵌套对象。
鉴于您的预期用例,使用具有复合键并使用.split().reduce()
方法在嵌套对象中获取所需值的查找功能最有意义。
所以,像这样:
function lookup(obj : object, key : string) : any {
return key.split('.').reduce((o, k) => o && o[k], obj);
}
像这样使用:
this.subscriptions.sort((val1, val2) => {
return lookup(val1,column) - lookup(val2,column);
});
答案 1 :(得分:0)
您的问题似乎不是将实际对象作为the initialValue
parameter传递了。
我们可以编写一个nestedProp()
函数,该函数接受一个对象和一个路径字符串并遍历它:
function nestedProp(obj: object, path: string): unknown {
return path.split(".").reduce((o, k) => o ? (o as any)[k] : undefined, obj);
}
我实际上所做的只是将obj
添加为initialValue
。我还防止o[k]
是null
或undefined
,以便在传递错误字符串时代码不会引发运行时错误。
还要注意,我给出的类型定义确实非常宽松; obj
是任何object
,path
是任何string
,并返回unknown
。那是因为TypeScript无法在类型级别上进行字符串操作,所以不知道"one.two.three".split(".")
会产生["one", "two", "three"]
,因此也不知道nestedProp()
应该产生{{1} }而不是string
,这是您传入undefined
时发生的情况。可以稍微加紧定义,但这似乎不值得。为了安全起见,应该测试输出是否是您想要的。
因此,让我们对其进行测试。说你的对象是这样的:
"oops.not.a.property"
然后您可以像这样呼叫const myObj = {
'one': {
'two': {
'three': 'val'
}
}
}
:
nestedProp()
对我很好。请注意,在假设输出为const res1 = nestedProp(myObj, "one.two.three");
console.log(res1); // "val"
console.log((typeof res1 === "string" ? res1 : "oops").toUpperCase()); // VAL
const res2 = nestedProp(myObj, "three.two.one");
console.log(res2); // undefined
console.log((typeof res2 === "string" ? res2 : "oops").toUpperCase()); // OOPS
之前,我正在测试输出是否为string
,如果不是,则使用"oops"
。好吧,希望能有所帮助;祝你好运!
答案 2 :(得分:-1)
let string = "one.two.three.four.five.six";
let stringArr = string.split('.');
let obj = {
[stringArr[stringArr.length - 1]]: "value",
}
for (let i = stringArr.length - 2; i >= 0; i--) {
this[stringArr[i]] = obj
obj = Object.assign({}, this)
delete this[stringArr[i]]
}
console.log(JSON.stringify(obj))
这适用于任何数量的嵌套。
{"one":{"two":{"three":{"four":{"five":{"six":"value"}}}}}}
我希望这就是你想要的