【问题标题】:Insert object into specific position in an array based off property match将对象插入到基于属性匹配的数组中的特定位置
【发布时间】:2021-05-29 22:36:26
【问题描述】:

我已经为此工作了几天,遗憾的是我无法找到正确的搜索词或我缺乏技能的正确答案。

我正在将 ListServ 转换为 Discourse。我正在将 RSS 提要转换为 JSON。 源数据示例:

  {
    "title": "tech: 18F presentation",
    "id": 2,
    "body": "Sadly, my biggest concern is whether it will run on Linux or Windows. And I guess if they’ll thrown even more java at it.",
    "date": "Fri, 28 May 2021 20:50:04 +0000",
    "author": "john_doe"
  },
  {
    "title": "Re: tech: 18F presentation",
    "id": 3,
    "body": "throw more java, indeed. What a moon shot.",
    "date": "Fri, 28 May 2021 20:50:04 +0000",
    "author": "john_doe2"
  },
  {
    "title": "Re: tech: 18F presentation",
    "id": 4,
    "body": "Please stop saying moonshot, its not dodgecoin",
    "date": "Fri, 28 May 2021 20:50:04 +0000",
    "author": "jane_doe"
  },

我的数据结构需要如下所示:

{
   "topics": [
      {
        "id": 1,
        "title": "tech: 18F presentation",
        "pinned": false,
        "posts": [
    {
     "title": "Re: tech: 18F presentation",
     "id": 3,
     "body": "throw more java, indeed. What a moon shot.",
     "date": "Fri, 28 May 2021 20:50:04 +0000",
     "author": "john_doe2"
     },
    {
     "title": "Re: tech: 18F presentation",
     "id": 4,
     "body": "Please stop saying moonshot, its not dodgecoin",
     "date": "Fri, 28 May 2021 20:50:04 +0000",
     "author": "john_doe2"
     },
        ]
      }
    ]
  }

我需要将带有“Re:”的每个标题插入到原始标题中。示例)任何回复,“Re tech: 18F Presentation”需要插入帖子:[] of the title: “tech: 18F presentation”(无 Re: )。

我尝试将回复分散到它自己的 json 中并将其推送到 post 数组中,但我无法弄清楚如何匹配适当的标题。

    let data = [];
  const original_post = [];
  const reply_to_post = [];
  const discourse_JSON = [];
    $("item").map(function (i, article) {
        const title = $(article).find("title")[0].children[0].data;
    const description = $(article).find("description")[0].children[0].data;
    const user_email = $(article).find("author")[0].children[0].data.match("<([^>]+)>")[1];
    const link = $(article).find("link")[0].children[0].data;
    const guid = $(article).find("guid")[0].children[0].data;
    const date = $(article).find("pubDate")[0].children[0].data;
    const name = user_email.substring(0,user_email.indexOf('@')).split("_")[0] + ' ' + user_email.substring(0,user_email.indexOf('@')).split("_")[1];
    const username = user_email.substring(0,user_email.indexOf('@'))
        if (
            !title.toLowerCase().includes("vacancy") &&
            !title.toLowerCase().includes("opportunity") &&
            !title.toLowerCase().includes("retirement") &&
      !title.toLowerCase().includes("position") &&
      !title.toLowerCase().includes("job posting") && 
      !description.toLowerCase().includes("vacancy announcement")  &&
      !description.toLowerCase().includes("vacancy posting") &&
      !description.toLowerCase().includes("vacancies")

        ) {
 

   data.push({
    "title": title,
    "id": i,
    "body": description,
    "date": date,
    "author": username







    }
});

【问题讨论】:

  • 您将需要遍历源数据,然后使用字符串匹配构建帖子数组。到目前为止你写过什么代码吗?

标签: javascript arrays object discourse


【解决方案1】:

这是一个使用Array.forEach 运算符的简单解决方案。可能有更有效的解决方案,如果您拥有大型数据集,这可能很重要:

const source = [{title:"tech: 18F presentation",id:2,body:"Sadly, my biggest concern is whether it will run on Linux or Windows. And I guess if they’ll thrown even more java at it.",date:"Fri, 28 May 2021 20:50:04 +0000",author:"john_doe"},{title:"Re: tech: 18F presentation",id:3,body:"throw more java, indeed. What a moon shot.",date:"Fri, 28 May 2021 20:50:04 +0000",author:"john_doe2"},{title:"Re: tech: 18F presentation",id:4,body:"Please stop saying moonshot, its not dodgecoin",date:"Fri, 28 May 2021 20:50:04 +0000",author:"jane_doe"}];

let = formatted = [];
// Loop over the original data, find parents
source.forEach((item) => {
  // Is not a reply
  if (item.title.indexOf('Re:') === -1) {
    formatted.push(item);
  }
});
// Find children, append to parents
source.forEach((item) => {
  formatted.forEach((parent) => {
    // Child contains parent title.
    if (item.title.indexOf(parent.title) !== -1 && item.title.indexOf('Re:') !== -1) {
      if (!parent.data) {
        parent.data = [];
      }
      parent.data.push(item);
    }
  })
});
console.log(formatted);

【讨论】:

    【解决方案2】:

    这实际上只是一个“groupBy”,通过一些字符串操作来确定层次结构。

    这是一个使用Array#reduce() 并检查标题startsWith() 'Re:' 的示例。如果是这样,请使用String#replace()trim() 删除初始的“Re:”以保持一致性。

    const
      input = [{ "title": "Re: Re: Re: tech: 18F presentation", "id": 3, "body": "throw more java, indeed. What a moon shot.", "date": "Fri, 28 May 2021 20:50:04 +0000", "author": "john_doe2" }, { "title": "tech: 18F presentation", "id": 2, "body": "Sadly, my biggest concern is whether it will run on Linux or Windows. And I guess if they’ll thrown even more java at it.", "date": "Fri, 28 May 2021 20:50:04 +0000", "author": "john_doe" }, { "title": "Re: tech: 18F presentation", "id": 4, "body": "Please stop saying moonshot, its not dodgecoin", "date": "Fri, 28 May 2021 20:50:04 +0000", "author": "jane_doe" }, { "title": "Re: other: Title", "id": 6, "body": "throw more java, indeed. What a moon shot.", "date": "Fri, 28 May 2021 20:50:04 +0000", "author": "john_doe2" }, { "title": "other: Title", "id": 5, "body": "Sadly, my biggest concern is whether it will run on Linux or Windows. And I guess if they’ll thrown even more java at it.", "date": "Fri, 28 May 2021 20:50:04 +0000", "author": "john_doe" },],
    
      byTopic = input.reduce((acc, { title, ...post }) => {
        if (title.startsWith('Re:')) {
          const topic = title.replace(/^(?:Re: ){1,}/, '').trim();
          acc[topic] || (acc[topic] = { posts: [] });
          acc[topic].posts.push({ title: topic, ...post });
          // using nullish coalescing assignment
          // (acc[topic] ??= { posts: [] }).posts.push({ title: topic, ...post });
        } else {
          acc[title] = {
            id: post.id, // your example changes id in the expected output, unsure of the logic
            title: title,
            pinned: false, // not sure where pinned is coming from
            posts: acc[title] ? acc[title].posts : []
            // using optional chaining and nullish coalescing
            // posts: acc[title]?.posts ?? []
          }
        }
        return acc;
      }, {})
    
    console.log(Object.values(byTopic));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    正如我在cmets中提到的那样,使用reduce()这种方式可以直接替换为外部累加器和for循环。这里使用for...of

    const input = [{ "title": "Re: Re: Re: tech: 18F presentation", "id": 3, "body": "throw more java, indeed. What a moon shot.", "date": "Fri, 28 May 2021 20:50:04 +0000", "author": "john_doe2" }, { "title": "tech: 18F presentation", "id": 2, "body": "Sadly, my biggest concern is whether it will run on Linux or Windows. And I guess if they’ll thrown even more java at it.", "date": "Fri, 28 May 2021 20:50:04 +0000", "author": "john_doe" }, { "title": "Re: tech: 18F presentation", "id": 4, "body": "Please stop saying moonshot, its not dodgecoin", "date": "Fri, 28 May 2021 20:50:04 +0000", "author": "jane_doe" }, { "title": "Re: other: Title", "id": 6, "body": "throw more java, indeed. What a moon shot.", "date": "Fri, 28 May 2021 20:50:04 +0000", "author": "john_doe2" }, { "title": "other: Title", "id": 5, "body": "Sadly, my biggest concern is whether it will run on Linux or Windows. And I guess if they’ll thrown even more java at it.", "date": "Fri, 28 May 2021 20:50:04 +0000", "author": "john_doe" },];
    
    const byTopic = {};
    
    for (const { title, ...post } of input) {
      if (title.startsWith('Re:')) {
        const topic = title.replace(/^(?:Re: ){1,}/, '').trim();
        byTopic[topic] || (byTopic[topic] = { title: topic, posts: [] });
        byTopic[topic].posts.push({ title: topic, ...post });
      } else {
        byTopic[title] = {
          id: post.id,
          title: title,
          pinned: false,
          posts: [],
          ...byTopic[title]
        }
      }
    };
    
    console.log(Object.values(byTopic));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 是的,示例是随机 id。我实际上需要将帖子的ID与回复相匹配。在这里很好抓。我一直在寻找减少作为答案。 reduce 的效率如何?
    • 在这种情况下,它没有嵌套循环和直接的累加器访问非常高效,但如果您愿意,您可以轻松地将回调逻辑移动到“for”循环。
    • 是 ??运营商打字稿?它错误:帖子:acc[title]?.posts ?? []
    • 那是Nullish coalescing operator (??),为了兼容性,可以用 OR 替换。
    • 编辑没有无效的操作符
    猜你喜欢
    • 2016-04-15
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 2022-01-15
    • 1970-01-01
    • 2012-12-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多