以特定方式重新排列 JSON 数据
Posted
技术标签:
【中文标题】以特定方式重新排列 JSON 数据【英文标题】:Rearrange JSON data in a specific way 【发布时间】:2020-07-16 17:37:29 【问题描述】:我有一个类似于以下内容的 JSON 数据集:
[
"name": "Concert 1",
"sponsors": [
"name": "Woolworths",
"location": "Mildura"
,
"name": "Coles",
"location": "Melbourne"
,
"name": "Metricon",
"location": "Wagga Wagga"
]
,
"name": "Concert 2",
"sponsors": [
"name": "Metricon",
"location": "Albert Park"
,
"name": "Woolworths",
"location": "Melbourne"
,
"name": "ALDI",
"location": "Bendigo"
]
,
"name": "Concert 3",
"sponsors": [
"name": "Holcim",
"location": "Bendigo"
,
"name": "Westpac",
"location": "Melbourne"
,
"name": "Coles",
"location": "Mildura"
]
]
我想在网页上以以下格式显示此 JSON 输出:
Location X
Sponsor X
Concert 1
Concert 2
-------
Sponsor Y
Concert 1
Location Y
Sponsor Y
Concert 1
Concert 2
------
--------
基本上,我必须在顶层显示 Location 并将其他元素显示为子元素,换句话说,将 JSON 数据集颠倒过来。
到目前为止,我已经尝试使用 VueJS 计算属性循环遍历 JSON 文件,但仍然没有运气。有人可以告诉我如何解决这个问题吗?
如果我在这里没有使用正确的技术术语,我很抱歉,因为我不确定当我们显示这样的内容时我们会调用什么。
【问题讨论】:
请贴出你目前拥有的JS代码。 欢迎来到 Stack Overflow!请使用tour(您将获得徽章!)并通读help center,尤其是How do I ask a good question? 您最好的选择是进行研究,search 以获取有关 SO 的相关主题,然后试一试.如果您在进行更多研究和搜索后遇到困难并且无法摆脱困境,请发布您的尝试minimal reproducible example,并具体说明您卡在哪里。人们会很乐意提供帮助。 【参考方案1】:数据的转换方法如下:
const data = [
"name": "Concert 1",
"sponsors": [
"name": "Woolworths","location": "Melbourne",
"name": "Coles","location": "Melbourne",
"name": "Metricon","location": "Wagga Wagga"
]
,
"name": "Concert 2",
"sponsors": [
"name": "Metricon","location": "Albert Park",
"name": "Woolworths","location": "Melbourne",
"name": "ALDI","location": "Bendigo"
]
,
"name": "Concert 3",
"sponsors": [
"name": "Holcim","location": "Bendigo",
"name": "Westpac","location": "Melbourne",
"name": "Coles","location": "Mildura"
]
];
const byLocation = data.reduce((r, con) => (con.sponsors.forEach(sp =>
if (!r[sp.location]) r[sp.location] = ;
if (!r[sp.location][sp.name]) r[sp.location][sp.name] = [];
r[sp.location][sp.name].push(con.name);
), r), );
console.log(byLocation);
以上解释:
要转换初始的data
Array 的音乐会
[
concert,
concert,
// ...
]
放入对象 - 所有属性名称(位置)都是唯一的
"location name 1": ,
"location name 2": ,
// ...
第一个想法是使用Array.prototype.reduce()
MDN:
const byLocation = data.reduce((resultObject, concert) =>
// Insert concert data into resultObject here
return resultObject; // Return the Object for the next iteration
, ); // << is the resultObject
为了简短起见,进行了一些重命名,通过使用 箭头函数的隐式返回(没有包装花括号),我们可以将上面的内容转换/缩短为:
const byLocation = data.reduce((r, con) => (/*Insert con data into r*/, r), );
所以con
是迭代Concert,r
是我们需要构建的Resulting final Object。
让我们通过forEach
填充r
对象-ing con.sponsors
数组
con.sponsors.forEach(sp => // sp is the iterating Sponsor
// If r["location name"] does not exists, create it as empty object
if (!r[sp.location]) r[sp.location] = ;
// If r["location name"]["Sponsor name"] does not exists, create it
// as an empty array
if (!r[sp.location][sp.name]) r[sp.location][sp.name] = [];
// Finally push the Concert name into that array.
r[sp.location][sp.name].push(con.name);
)
如果概念太高级,也可以这样写:
const data = [
"name": "Concert 1",
"sponsors": [
"name": "Woolworths","location": "Melbourne",
"name": "Coles","location": "Melbourne",
"name": "Metricon","location": "Wagga Wagga"
]
,
"name": "Concert 2",
"sponsors": [
"name": "Metricon","location": "Albert Park",
"name": "Woolworths","location": "Melbourne",
"name": "ALDI","location": "Bendigo"
]
,
"name": "Concert 3",
"sponsors": [
"name": "Holcim","location": "Bendigo",
"name": "Westpac","location": "Melbourne",
"name": "Coles","location": "Mildura"
]
];
const byLocation = ; // The resulting object of unique Locations
data.forEach((concert) =>
const sponsors = concert.sponsors;
sponsors.forEach((sponsor) =>
if (!byLocation.hasOwnProperty(sponsor.location))
byLocation[sponsor.location] = ;
if (!byLocation[sponsor.location].hasOwnProperty(sponsor.name))
byLocation[sponsor.location][sponsor.name] = [];
byLocation[sponsor.location][sponsor.name].push(concert.name);
);
);
console.log(byLocation);
用 javascript 显示 <ul id="list"></ul>
内的数据:
const html = Object.entries(byLocation).reduce((h, [location, ob]) =>
h += `<li>$location<ul>`;
Object.entries(ob).forEach(([sponsor, concerts]) =>
h += `<li>$sponsor
<ul>
<li>$concerts.join('</li><li>')</li>
</ul>
</li>`;
);
h += `</ul></li>`;
return h
, '');
document.querySelector('#list').insertAdjacentHTML('beforeend', html);
【讨论】:
嘿 Roko,非常感谢您的回答,这救了我。如果我要求您解释您编写的代码,会不会太过分了?这一切都很好,就像一个魅力,但我想了解你在这里究竟做了什么,特别是reduce()
的使用。如果你能放一些 cmets 那就太好了,它会帮助我和接下来寻找这样的东西的人。再次感谢。
@Dynamdilshan 下面是 reduce 的语法:array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
。所以,Roko 正在做的是:r
:reduce 的“total”,这意味着最后将返回的值。 con
:当前演唱会。然后,他遍历每场音乐会的赞助商,并在 r
对象上创建一个条目(如果尚不存在),并且与赞助商名称相同。最后,initialValue
是r
在reduce
函数的第一次迭代中的值,在这种情况下是一个空对象(
)。希望这会有所帮助。
谢谢@tintef 非常感谢您的帮助!我还添加了一些解释。
嗨@RokoC.Buljan,如果我来回处理这个问题,我很抱歉。我对这个解决方案有最后一个问题。如果我想按字母顺序对所有这些条目进行排序,我该怎么做?你能指点我正确的方向吗?。
@Dynamdilshan 请提出一个新问题,如果有超出此范围的内容。【参考方案2】:
一个简单的解决方案是:
将你的 json 数据传递给你的数据对象中的 vue
添加一个计算属性“formattedData”,并提供一个函数,将 json 数据格式化为您需要的格式。
在模板中使用此计算属性来呈现数据。我将大致说明您可以做什么:
var concertData = [
"name": "Concert 1",
"sponsors": [
"name": "Woolworths",
"location": "Mildura"
,
"name": "Coles",
"location": "Melbourne"
,
"name": "Metricon",
"location": "Wagga Wagga"
]
,
"name": "Concert 2",
"sponsors": [
"name": "Metricon",
"location": "Albert Park"
,
"name": "Woolworths",
"location": "Melbourne"
,
"name": "ALDI",
"location": "Bendigo"
]
,
"name": "Concert 3",
"sponsors": [
"name": "Holcim",
"location": "Bendigo"
,
"name": "Westpac",
"location": "Melbourne"
,
"name": "Coles",
"location": "Mildura"
]
];
new Vue(
data:
concerts: concertData // pass your concert json here
,
computed:
formattedData: function ()
var formattedData = new Map();
this.concerts.forEach(function (item)
item.sponsors.forEach(function (sponsor)
if (!formattedData.has(sponsor.location))
formattedData.set(sponsor.location, new Map());
if (!formattedData.get(sponsor.location).has(sponsor.name))
formattedData.get(sponsor.location).set(sponsor.name, []);
formattedData.get(sponsor.location).get(sponsor.name).push(item.name);
)
);
return formattedData;
,
render: function(h)
// loop over this.formattedData to paint the display
).$mount("#app");
【讨论】:
以上是关于以特定方式重新排列 JSON 数据的主要内容,如果未能解决你的问题,请参考以下文章