基于属性匹配将对象插入到数组中的特定位置

问题描述

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

我正在将 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.","author": "john_doe2"
  },"id": 4,"body": "Please stop saying moonshot,its not dodgecoin","author": "jane_doe"
  },

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

{
   "topics": [
      {
        "id": 1,"title": "tech: 18F presentation","pinned": false,"posts": [
    {
     "title": "Re: tech: 18F presentation","author": "john_doe2"
     },{
     "title": "Re: tech: 18F presentation",]
      }
    ]
  }

我需要将每个带有“Re:”的标题插入到原始标题中。示例)任何回复,“Re tech:18F 演示文稿”需要插入帖子:[] 的标题:“tech:18F 演示文稿”(没有 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







    }
});

解决方法

这实际上只是一个“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.","author": "john_doe" },{ "title": "Re: tech: 18F presentation","id": 4,"body": "Please stop saying moonshot,its not dodgecoin","author": "jane_doe" },{ "title": "Re: other: Title","id": 6,{ "title": "other: Title","id": 5,],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; }

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

const input = [{ "title": "Re: Re: Re: tech: 18F presentation",];

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,posts: [],...byTopic[title]
    }
  }
};

console.log(Object.values(byTopic));
.as-console-wrapper { max-height: 100% !important; top: 0; }

,

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

const source = [{title:"tech: 18F presentation",id:2,body:"Sadly,date:"Fri,author:"john_doe"},{title:"Re: tech: 18F presentation",id:3,body:"throw more java,author:"john_doe2"},id:4,body:"Please stop saying moonshot,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);

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...