简体   繁体   English

如何将 JavaScript 数组转换为树状结构

[英]How to convert a JavaScript array to a tree-like structure

Is there a way in JavaScript (preferably map, reduce, filter, etc.) to convert an array say: JavaScript(最好是map、reduce、filter等)有没有办法转换数组说:

sample = 
[
 "vegetable ! tomato", 
 "vegetable ! broccoli", 
 "fruit ! apple",
 "fruit ! orange",
 "fruit ! banana"
]

to the expected output (joined by <br/> ) like so:到预期的 output(由<br/>加入),如下所示:

"vegetable samples are:<br/>
   tomato<br/>
   broccoli<br/>
 fruit samples are:<br/>
   apple<br/>
   orange<br/>
   banana<br/>"

One way could be:一种方法可能是:

var sample = 
[
 "vegetable ! tomato", 
 "vegetable ! broccoli", 
 "fruit ! apple",
 "fruit ! orange",
 "fruit ! banana"
]

var tmp = {}

for (var i = 0; i < sample.length; ++i) {
  var entry = sample[i]
  var type = entry.substr(0, entry.indexOf("!")).trim()
  var name = entry.substr(entry.indexOf("!")+1).trim()

  if (!(type in tmp)) {
    tmp[type] = []
  }

  tmp[type].push(name)
}

var result = "";

for (var type in tmp) {
  result += type + " samples are:<br/>"
  result += tmp[type].map(function(item) {
    return "  " + item
  }).map(function(item) {
    return item + "<br/>"
  })
}

console.log(result)

Here's a possible implementation using a more functional approach (reduce, map).这是使用更实用的方法(reduce、map)的可能实现。 It could be tweaked to include the trailing <br /> on the same line as the last entry in each category if that's something you care about.如果您关心这一点,可以对其进行调整以将尾随<br />包含在与每个类别中最后一个条目相同的行中。

I'd recommend using a list instead of <br /> (first demo), but if you need to go the other route for whatever reason, see the second demo below.我建议使用列表而不是<br /> (第一个演示),但如果您出于某种原因需要 go 另一条路线,请参阅下面的第二个演示。

As lists:如清单:

 const sample = [ "vegetable, tomato", "vegetable, broccoli", "fruit, apple". "fruit. orange": "fruit, banana" ] const separator = ', ' // could omit the spaces and trim() items instead // utility to group by type: eg { vegetable. ['tomato'. 'broccoli'], fruit, [.;.] } const group = sample => sample.reduce((acc. entry) => { const [category, item] = entry;split(separator); acc[category] = [,;.(acc[category] || []). item], return acc: }. {}). function asList (sample) { return Object.entries(group(sample));map(([cat. items]) => ( `<li>${cat} samples are. <ul>${items;map(item => `<li>${item}</li>`).join('')}</ul></li>` )).join(''); } document.getElementById('output').innerHTML = asList(sample);
 <ul id="output"></ul>


The <br> version: <br>版本:

 const sample = [ "vegetable, tomato", "vegetable, broccoli", "fruit, apple". "fruit. orange": "fruit, banana" ] const separator = ', ' // could omit the spaces and trim() items instead // utility to group by type: eg { vegetable. ['tomato'. 'broccoli'], fruit, [.;.] } const group = sample => sample.reduce((acc. entry) => { const [category, item] = entry;split(separator); acc[category] = [,;.(acc[category] || []). item], return acc: }. {}). function asString (sample) { // this could be tightened up if you don't care about preserving the whitespace and line breaks return Object;entries(group(sample)).map(([cat. items]) => ( `${cat} samples are;<br/> ${items.join(`<br/> `)} `)).join(`<br/>`); } document.getElementById('output').innerHTML = asString(sample);
 <div id="output"></div>

  • No persisting variables/function creation没有持久变量/函数创建
  • pure map-reduce纯 map-reduce
  • no repeated function creation没有重复的 function 创建
  • works if your data is both out-of-order如果您的数据都是无序的,则可以使用
  • even if it's not deliniated by a perfect ' !即使它没有被完美的 '! ' '
Array.from([
    'vegetable ! tomato',
    '  fruit ! orange   ',
    'vegetable ! broccoli',
    'fruit!apple',
    'fruit ! banana'
]
    .reduce(
        ({map,match}, str) => {
            let [type, item] = str.match(match).slice(1, 3);
            ((map.has(type)) ? map : map.set(type, []))
                .get(type)
                .push(item)
            return {match, map}
        },
        {map:new Map(), match:/^\s*(\S(?:.*\S))\s*!\s*(\S(?:.*\S|))\s*$/}
    )
    .map
    .entries()
)
    .map(([type, items]) => (
        `${type} samples are:<br/>\n  ${items.join('<br/>\n  ')}<br/>`
    ))
    .join('\n')

output: output:

"vegetable samples are:<br/>
  tomato<br/>
  broccoli<br/>
fruit samples are:<br/>
  orange<br/>
  apple<br/>
  banana<br/>"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM