文章数组根据主题归类为Java约简

时间:2018-07-24 20:39:32

标签: javascript arrays multidimensional-array reduce

我正在尝试根据第一个键值对将文章数组拆分为子数组,并按顺序排列。

我研究了很多Stack Overflow帖子,并且我认为这是最适合我要完成的任务的

break array of objects into separate arrays based on a property

我知道通常会遇到关于reduce的问题,但是我被绊倒了,这就是我找不到答案的原因。

有什么不同:我不想将数组过滤到2个单独的类别(即“标记”和“视频”)中,而是让第一个数组全部是“标记” ”项,直到成为“视频”项为止,对所有“视频”项进行排列,直到下一个“标记”项为止,对所有“标记”项进行新的排列,直到下一个“视频”项,依此类推。

以下是REPL再现了我想做的事情: REPL reproducing problem

数据如下:

export default [{
  "type": "markup",
  "element": "p",
  "html": "blah"
}, {
  "type": "markup",
  "element": "p",
  "html": "blah"
}, {
  "type": "markup",
  "element": "p",
  "html": "blah"
}, {
  "type": "embeddedVideo",
  "element": "p",
  "html": "embeddedWidget"
}, {
  "type": "markup",
  "element": "p",
  "html": "blah"
},
{
  "type": "markup",
  "element": "p",
  "html": "blah"
},
]

使用JavaScript reduce后,我想要的样子是:

[
  [
    {type: 'markup', element: 'p', html: 'blah' /*...*/ },
    {type: 'markup', element: 'p', html: 'blah' /*...*/ },
    {type: 'markup', element: 'p', html: 'blah' /*...*/ }
  ],
  [
    {type: 'embeddedVideo', /*...*/ }
  ],
  [
    {type: 'markup', element: 'p', html: 'blah' /*...*/ },
    {type: 'markup', element: 'p', html: 'blah' /*...*/ },
    {type: 'markup', element: 'p', html: 'blah' /*...*/ }
  ]
]

我到目前为止的是:

import articleBody from './articleBody.js';


 function groupBy(arr, property) {
  return arr.reduce((prop, x) => {
    if (!prop[x[property]]) { prop[x[property]] = []; }
    prop[x[property]].push(x);
    return prop;
  }, {});
}

let outputSample = groupBy(articleBody, "type");

console.log(outputSample)

此代码仅创建了2个数组(一个带有标记,一个带有视频),它没有记住原始数据的顺序,也没有根据顺序为所有数据组创建单独的数组。 / p>

解决此问题的最优雅方法是什么?如果您能正确地指导我,我将不胜感激。

5 个答案:

答案 0 :(得分:2)

您可以使用Array#reduce并检查累加器的最后一个元素。

var array = [{ type: "markup", element: "p", html: "blah" }, { type: "markup", element: "p", html: "blah" }, { type: "markup", element: "p", html: "blah" }, { type: "embeddedVideo", element: "p", html: "embeddedWidget" }, { type: "markup", element: "p", html: "blah" }],
    grouped = array.reduce((r, o, i, a) => {
        var last = r[r.length - 1];
        if (!last || last[0].type !== o.type) {
            r.push([o]);
        } else {
            last.push(o);
        }
        return r;
    }, []);

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

答案 1 :(得分:1)

我知道for不如reduce酷,但它的可读性肯定更高:

 const result = [[]];
 let current = result[0], currentType = articleBody[0].type;

 for(const content of articleBody) {
   if(content.type === currentType) {
     current.push(content);
   } else {
     result.push(current = [content]);
     currentType = content.type;
  }
}

答案 2 :(得分:1)

要使用reduce()进行此操作,您只需关注最后看到的内容,然后将一个新数组(如果结果不同)推入结果,然后推入倒数第二个子数组。在眼睛上进行定期循环可能会更容易一些。

let tempArr = [{"type": "markup","element": "p","html": "blah"}, {"type": "markup","element": "p","html": "blah"}, {"type": "markup","element": "p","html": "blah"}, {"type": "embeddedVideo","element": "p","html": "embeddedWidget"}, {"type": "markup","element": "p","html": "blah"},{"type": "markup","element": "p","html": "blah"},]

let r = tempArr.reduce((a, c, i, self) => {
    if (i === 0 || self[i-1].type !== c.type) 
        a.push([])
    a[a.length - 1].push(c)
    
    return a
}, [])

console.log(r)

答案 3 :(得分:0)

这是我的版本:)

const input = [{
  "type": "markup",
  "element": "p",
  "html": "blah"
}, {
  "type": "markup",
  "element": "p",
  "html": "blah"
}, {
  "type": "markup",
  "element": "p",
  "html": "blah"
}, {
  "type": "embeddedVideo",
  "element": "p",
  "html": "embeddedWidget"
}, {
  "type": "markup",
  "element": "p",
  "html": "blah"
}];

const property = 'type';
const collection = [[]];
let found = input[0][property];
input.reduce((prev, next) => {
  if (found === next[property]) {
    prev.push(next);
    return prev;
  } else {
      collection.push([next]);
      found = next[property];
      return collection[collection.length - 1];
  }
}, collection[0]);

console.log('Collection', collection);

答案 4 :(得分:0)

此两步简化功能的说明:

  1. 如果类型与上一个条目不匹配或没有上一个 进入,将新行推到累加器上。

  2. 将当前对象添加到最新行。

const data = [{
    "type": "markup",
    "element": "p",
    "html": "blah"
  }, {
    "type": "markup",
    "element": "p",
    "html": "blah"
  }, {
    "type": "markup",
    "element": "p",
    "html": "blah"
  }, {
    "type": "embeddedVideo",
    "element": "p",
    "html": "embeddedWidget"
  }, {
    "type": "markup",
    "element": "p",
    "html": "blah"
  },
  {
    "type": "markup",
    "element": "p",
    "html": "blah"
  },
];

const result = data.reduce((a, e) => {
  if (!a[0] || e.type !== a[a.length-1].type) {
    a.push([]);
  }
  
  a[a.length-1].push(e);      
  return a;
}, []);

console.log(result);