es6从数组解构为对象的语法

时间:2016-03-22 05:43:11

标签: javascript ecmascript-6

我正在读取带有制表符分隔值的文件,我想将其转换为带有命名属性的哈希数组。

我已经研究过the MDN page on Destructuring assignment,但是一些更复杂的例子对我没有意义,我没有看到导致单个对象的语法。

这是我到目前为止所得到的:

return File.readFile(filepath, 'utf8')
.then((fileContents) => fileContents.split('\n').map((line) => {
    // here is where I'd convert the line of tab-separated
    // text into an object with named properties

    // this is fake, broken syntax
    return ({ prop_a: [0], prop_b: [2], prop_c: [1] }) = line.split('\t');
}));

有几点需要注意:

  • 我正在使用带有节点v5的babel。如果有必要,我愿意加载额外的解析或转换插件。
  • File.readFile是一个围绕节点原生fs.readFile(path, opt, callback) API的简单ES6 Promise包装器。

我正在寻找一个可以拆分line并从中任意分配给新创建的对象的语句。我认为解构是解决这个问题的正确方法,但也许所需要的是例如休息或传播的一些创造性用途。

// sample input text
Ralphette   dog 7
Felix   cat 5

// desired output
[ { name: 'Ralphette', species: 'dog', age: '7' },
  { name: 'Felix'    , species: 'cat', age: '5' }
]

感谢您的帮助!

ANSWER

听起来似乎没有办法只通过解构来做到这一点。然而,在混合物中引入IIFE使得单衬里具有不太奇特的解构。这是我使用的代码,基于@Amadan的答案:

return File.readFile(filepath, 'utf8')
.then((fileContents) => (fileContents.length === 0)
    ? []
    : fileContents
        .split('\n')
        .map((line) => (([ name, species, age ]) => ({ name, species, age }))(line.split('\t')))
)

这很简洁,因此我建议不要在真实的项目中使用它。

如果,从现在开始,有人发现没有IIFE的方法,我希望他们会发布它。

3 个答案:

答案 0 :(得分:3)

可能不是你想要的,但最接近的可能是

(x => ({ prop_a: x[0], prop_b: x[2], prop_c: x[1] }))(line.split('\t'));

但这可能是最容易做到的

var parts = line.split('\t');
return { prop_a: parts[0], prop_b: parts[2], prop_c: parts[1] };

虽然我可能被证明是错的,但我认为你想要的东西不能通过解构分配来完成。

答案 1 :(得分:3)

您无法将数组直接解构为对象

这个答案采用分解的方法,而不是将所有东西捆绑在一个大乱的功能中。这里的各个功能更易于编写,维护和测试。执行单个任务的小功能也更容易在程序的其他部分重用。

const lines = x => x.split("\n")
const cells = x => x.split("\t")
const makeObject = ([name, species, age]) => ({name, species, age})

const data = "Ralphette\tdog\t7\nFelix\tcat\t5"
const result = lines(data).map(x => makeObject(cells(x)))

console.log(result)
// [ { name: "Ralphette", species: "dog", age: "7" }
// , { name: "Felix", species: "cat", age: "5" }
// ]

如果您有compose功能,它会变得更加清晰

const compose = (f,g) => x => f(g(x))

const result = lines(data).map(compose(makeObject,cells))

console.log(result)
// [ { name: "Ralphette", species: "dog", age: "7" }
// , { name: "Felix", species: "cat", age: "5" }
// ]
  

如果,从现在开始,有人发现没有IIFE的方法,我希望他们会发布它。

已经有几年了,所以这里是你的答案的编辑,不涉及立即调用的函数 -

File
  .readFile(filepath, 'utf8')
  .then
    ( fileContents => 
        fileContents.length === 0
          ? []
          : fileContents
              .split('\n')
              .map(line => line.split('\t'))
              .map(([ name, species, age ]) => ({ name, species, age }))
    )

这实际上与我上面的原始答案做了同样的事情,只是效率较低,因为它使用了两次map调用。以下是将linescellsmakeObject与原始代码相关联的方法 -

File
  .readfile(filepath, 'utf8')
  .then
    ( fileContents => 
        fileContents.length === 0
          ? []
          : lines(fileContents).map(line => makeObject(cells(line))
    )

还有一件事......

  

File.readFile是一个围绕节点本地fs.readFile(路径,选择,回调)API的简单ES6 Promise包装器

节点现在附带Promise-based API for the fs module。您可以简单地 - 而不是定义自己的包装器 -

const { readFile } = require("fs").promises

readFile(filePath, 'utf8').then(results => ...)

答案 2 :(得分:1)

这可能是另一个最接近的:

var parts = line.split('\t');
var [name, species, age] = parts;
return {name, species, age};