【问题标题】:Rearrange JSON data in a specific way以特定方式重新排列 JSON 数据
【发布时间】: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,并具体说明您卡在哪里。人们会很乐意提供帮助。

标签: javascript arrays json vue.js


【解决方案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 显示 &lt;ul id="list"&gt;&lt;/ul&gt; 内的数据:

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 对象上创建一个条目(如果尚不存在),并且与赞助商名称相同。最后,initialValuerreduce 函数的第一次迭代中的值,在这种情况下是一个空对象({})。希望这会有所帮助。
  • 谢谢@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");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    • 2017-12-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多