我想基于另一个对象中的点符号字符串来转换对象。例如:
const objToTransform = {
"a": "aValue",
"b": {
"c": "cValue",
"d": "dValue"
}
};
const filteringObj = {
"field1": "a",
"field2": {
"subfield1": "b.c",
"subfield2": "b.d"
}
};
const filteredObj = myFunc(objToTransform, filteringObj);
// expect outputs to be:
// {
// "field1": "aValue",
// "field2": {
// "subfield1": "cValue",
// "subfield2": "dValue"
// }
// }
我已经在这个看似简单的事情上工作了几个小时,但仍然无法正常工作。我发现了this topic,它向您展示了如何使用点符号字符串获取嵌套的对象值,但又很难过。
在此先感谢您的帮助!
答案 0 :(得分:0)
您可以使用递归在以下步骤中进行操作:
filteringObj
。getByPath
,该函数获取对象和路径并从嵌套对象返回该路径处的值transform
,该函数遍历filteringObj
的键(我在函数中将其命名为pattern
)transform
函数objectToTransform
函数从原始对象getByPath
获取值
const objToTransform = {
"a": "aValue",
"b": {
"c": "cValue",
"d": "dValue"
}
};
const filteringObj = {
"field1": "a",
"field2": {
"subfield1": "b.c",
"subfield2": "b.d"
}
};
function getByPath(obj, path){
//console.log(path)
return path.split('.').reduce((ac,a) => ac[a], obj);
}
function transform(obj, pattern){
for(let key in pattern){
if(typeof pattern[key] === "object"){
transform(obj, pattern[key]);
}
else{
pattern[key] = getByPath(obj, pattern[key]);
}
}
}
const copy = JSON.parse(JSON.stringify(filteringObj))
transform(objToTransform, copy);
console.log(copy)
答案 1 :(得分:0)
您可以使用Mono.fromSupplier(() -> StringUtils.isEmailValid(signInRequest.getUserName()))
.filter(o -> o)
.flatMap(o -> userService.findByEmail(signInRequest.getUserName()))
.switchIfEmpty(userService.findByUsername(signInRequest.getUserName()))
...
方法创建递归函数,该方法每次在值的类型为object时都会创建递归调用。
reduce
答案 2 :(得分:0)
我做了一个递归算法:
library(shiny)
library(shinyjs)
ui <- fluidPage(
actionButton("do", "Click Me"),
verbatimTextOutput("eventTimeRemaining"),
imageOutput("msg")
)
server <- function(input, output, session) {
EventTime <- reactiveVal(Sys.time())
observeEvent(input$do,{
EventTime(Sys.time() + 3)
})
timeLeft <- reactive({
tl <- round(difftime(EventTime(), Sys.time(), units='secs'))
if (tl > 0) {
invalidateLater(1000, session)
}
tl
})
output$eventTimeRemaining <- renderText({
timeLeft()
})
output$msg <- renderImage({
if (timeLeft() > 0) {
list(src = '')
} else {
list(src = './sing.jpg')
}
}, deleteFile = FALSE)
}
shinyApp(ui, server)
答案 3 :(得分:0)
Lodash使您可以非常轻松地使用点表示法。 这正是您想要的(<10行):
import _ from "lodash";
const objToTransform = {
a: "aValue",
b: {
c: "cValue",
d: "dValue"
}
};
const filteringObj = {
field1: "a",
field2: {
subfield1: "b.c",
subfield2: "b.d"
}
};
const filter = (model, data, filtered = {}) => {
for (const field in model) {
filtered[field] =
typeof model[field] === "object"
? filter(model[field], data, model[field])
: _.get(objToTransform, model[field]);
}
return filtered;
};
console.log(filter(filteringObj, objToTransform))
答案 4 :(得分:0)
如果您正在使用(或有兴趣使用)Ramda(免责声明:如果我是其主要作者之一),那么这可能对您有用。 Ramda没有deepMap
函数,但是编写函数很容易。并使用它,您的转换函数是一线的:
const deepMap = (fn) => (obj) =>
is (Object, obj) ? map (deepMap (fn)) (obj) : fn (obj)
const transform = compose(applySpec, deepMap (compose (path, split('.'))))
const objToTransform = {a: "aValue", b: {c: "cValue", d: "dValue"}}
const filteringObj = {field1: "a", field2: {subfield1: "b.c", subfield2: "b.d"}}
console .log (transform (filteringObj) (objToTransform))
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
<script> const {is, map, compose, applySpec, path, split } = R </script>
这里的关键点是applySpec
,您可以直接使用filteringObj
稍有不同的格式。这将产生您想要的结果:
applySpec ({
field1: path (["a"]),
field2: {
subfield1: path (["b", "c"]),
subfield2: path (["b", "d"])
}
}) (objToTransform)
transform
函数的其余部分只是将filteringObj
转换为上面的形式。
如果您要继续按照问题中的要求来调用它,即使用transform (objToTransform, filteringObj)
而不是trasform (filteringObj) (objToTransform)
,则只会稍微复杂一点:
const transform = (objToTransform, filteringObj) =>
applySpec(deepMap (compose (path, split('.'))) (filteringObj)) (objToTransform)
您可以编写自己的Ramda函数版本,即mostly easy。但是适用于嵌套属性的applySpec
版本会更加困难。