我正在遍历嵌套对象。返回数据由两个数组包装。我理解为什么会这样,但是我不明白如何获取所需的数据。
const data = {
"foo": {
"bar": {
"id": "1",
"step": [{
"id": "33",
"copy": [{
"id": "1",
"text": "hello",
},
{
"id": "2",
"text": "whirl",
},
{
"id": "3",
"text": "whoa",
}
],
}]
}
}
}
pipe(
path(['foo', 'bar', 'step']),
map(step =>
step.copy.map(s => ({text: s.text}))
)
) (data)
返回数据返回此:
[[{"text": "hello"}, {"text": "whirl"}, {"text": "whoa"}]]
我想把这个退回去
[{"text": "hello"}, {"text": "whirl"}, {"text": "whoa"}]
答案 0 :(得分:2)
问题在于step
本身就是array
。您需要获取其第一项或在参数中传递0
。这是从路径查找数据的纯js版本。我使用了reduce()
const data = { "foo": { "bar": { "id": "1", "step": [{ "id": "33", "copy": [{ "id": "1", "text": "hello" }, { "id": "2", "text": "whirl" }, { "id": "3", "text": "whoa" } ] }] } } }
function getFromPath(obj, path) {
return path.reduce((ac, a) => ac[a] || {}, obj);
}
let res = getFromPath(data, ["foo","bar","step",0,"copy"]).map(({text}) => ({text}))
console.log(res)
答案 1 :(得分:1)
使用 Ramda.js 来实现所需功能的一种解决方案是在app.use('/', function (req, res, next) {
// Check 1
console.log('Request URL:', req.originalUrl)
next()
}, function (req, res, next) {
// Check 2: Pass first check
console.log('Request Type:', req.method)
next()
})
app.get('/', (req, res) => {
// Final Route
});
之后插入https://expressjs.com/en/guide/using-middleware.html。
app.use('/first', function (req, res, next) {
passport.use(
new GoogleStrategy({
callbackURL: '/google/redirect',
clientID: keys.google.clientID,
clientSecret: keys.google.clientSecret
}, function (accessToken, refreshToken, profile, done){
if (profile._json.hd === "HIDDEN-DOMAIN.COM") {
User.findOne({googleId : profile.id})
.then(function(currentUser){
if(currentUser){
console.log('User with ID' + currentUser.googleId +' already exists. No new entry was made');
done(null, currentUser);
} else {
new User({
username: profile.displayName,
googleId: profile.id
})
.save()
.then(function(newUser){
console.log('New user created: ' + newUser);
done(null, newUser);
next(); // next();
});
}
})
} else {
console.log(__dirname);
next(); // next();
}
}));
}, function (req, res, next) {
// More checks
next()
});
app('/', (req, res) => {
// final route here
res.sendFile('../login.html');
})
R.map()
const data = {
"foo": {
"bar": {
"id": "1",
"step": [{
"id": "33",
"copy": [
{"id": "1", "text": "hello"},
{"id": "2", "text": "whirl"},
{"id": "3", "text": "whoa"}
],
}]
}
}
}
let res = R.pipe(
R.path(['foo', 'bar', 'step']),
R.map(step => step.copy.map(s => ({text: s.text}))),
R.flatten
) (data)
console.log(res);
另一种解决方案可能是将外部.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
替换为R.flatten:
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
R.map()
const data = {
"foo": {
"bar": {
"id": "1",
"step": [{
"id": "33",
"copy": [
{"id": "1", "text": "hello"},
{"id": "2", "text": "whirl"},
{"id": "3", "text": "whoa"}
],
}]
}
}
}
let res = R.pipe(
R.path(['foo', 'bar', 'step']),
R.reduce((acc, curr) => acc.concat(curr.copy.map(({text}) => ({text}))), [])
) (data)
console.log(res);
答案 2 :(得分:1)
我对您的代码最简单的解决方法是将外部map
替换为chain
。您可以选择使用flatten
,或者最好使用unnest
,但可以将chain
认为(至少在应用于数组时;实际上更通用)为map
然后是unnest
。
那会做你想要的。但是我建议,如果您要对其余部分使用无点Ramda代码,则还应替换内部的lambda以达到以下目的:
const transform = pipe(
path(['foo', 'bar', 'step']),
chain(prop('copy')),
project(['text'])
)
const data = {"foo": {"bar": {"id": "1", "step": [{"copy": [{"id": "1", "text": "hello"}, {"id": "2", "text": "whirl"}, {"id": "3", "text": "whoa"}], "id": "33"}]}}}
console.log(transform(data))
<script src="//bundle.run/ramda@0.26.1"></script>
<script>
const {pipe, path, chain, prop, project} = ramda
</script>
这对我来说看起来不错。但是请注意,解压缩使原始JS处理起来比以前更加整洁。这也应该起作用:
const transform = ({foo: {bar: {step}}}) => step.flatMap(
({copy}) => copy.map(({text}) => ({text}))
)
const data = {"foo": {"bar": {"id": "1", "step": [{"copy": [{"id": "1", "text": "hello"}, {"id": "2", "text": "whirl"}, {"id": "3", "text": "whoa"}], "id": "33"}]}}}
console.log(transform(data))
在这种情况下,Ramda版本对我来说更容易阅读,但只有很小的差异。
答案 3 :(得分:0)
由于副本包含一个数组,因此需要指定您要遍历该数组的位置。然后您有了正确的想法,然后更改值。
此
step.copy.map(s => ({text: s.text}))
需要成为
data['foo']['bar']['step'][0]['copy'].map(s => ({text: s.text}))
或 data.foo.bar.step[0].copy
data.foo.bar.step.map(v => {
return v.copy.map(v => {
return { text: v.text}
})
});
示例
const data = {
"foo": {
"bar": {
"id": "1",
"step": [{
"id": "33",
"copy": [{
"id": "1",
"text": "hello",
},
{
"id": "2",
"text": "whirl",
},
{
"id": "3",
"text": "whoa",
}
],
}]
}
}
}
// Output: [{"text": "hello"}, {"text": "whirl"}, {"text": "whoa"}]
let sorted = data['foo']['bar']['step'][0]['copy'].map(s => ({text: s.text}))
// let sorted = data.foo.bar.step[0].copy.map(s => ({text: s.text}))
console.log(sorted);
然后您可以管道
pipe(sorted)
答案 4 :(得分:-2)
获得一个或多个数组的原因是因为step
值可以迭代。删除数组的2层意味着您仅限制了step
数组的单个值:
pipe(
path(['foo', 'bar', 'step', '0', 'copy']),
map(s => ({text: s.text}))
) (data)
或
您要将所有step
值合并到单个外部数组。
flatten(pipe(
path(['foo', 'bar', 'step']),
map(step =>
step.copy.map(s => ({text: s.text}))
),
) (data))