将数据分组到单独的列表

时间:2016-07-26 15:22:02

标签: javascript jquery arrays

所以我现在正在经历一些逻辑上的难题。这是我试图解决的问题

问题

我正在读取PDB文件,当它浏览文件时,它会创建文件中所有链的列表。该列表看起来像这样

 chainIdList = [A, E, D, F, G, H];

长度可以变化。

我有序列中每个残基的所有chainIds的另一个列表,数据是我做的字典,看起来像这样

chainResidue = {"chainId" : chainId, "residueNumber" : residueNumber}
chainResidue = { "A", "4"} 

所以我想要做的是遍历chainResidues列表并检查chainResidue.chainId是否在chainList中。如果是,则创建一个匹配的chainId的新列表,然后将所有residualNumbers附加到该列表。

如果这有意义吗?

所以最后看起来像

A = [ 4, 6, 7, 8, ... and so on];
E = [ 9, 10];

到目前为止的代码

for (var i = 0; i < chainResidue.length; ++i) {
    for (var j = 0; j < chainList.length; ++j) {
        if (chainResidue[i].chainId === chainList[j]) {
           //Append value of the chainResidue[i].residueName into chainList[j] make a list of lists?
        }
    }
 }

示例数据

ATOM   3434  CA  LEU Y  17      -3.567   5.653  33.836  1.00 28.21           C  
ATOM   3435  C   LEU Y  17      -3.114   6.290  32.530  1.00 31.33           C  
ATOM   3436  O   LEU Y  17      -2.020   6.873  32.474  1.00 26.01           O  
ATOM   3437  CB  LEU Y  17      -2.620   4.575  34.233  1.00 29.46           C  
ATOM   3438  CG  LEU Y  17      -2.610   4.263  35.705  1.00 33.42           C  
ATOM   3439  CD1 LEU Y  17      -1.430   3.363  35.960  1.00 40.68           C  
ATOM   3440  CD2 LEU Y  17      -2.351   5.483  36.559  1.00 40.12           C  
ATOM   3441  N   ASP Y  18      -3.926   6.263  31.454  1.00 30.62           N  
ATOM   3442  CA  ASP Y  18      -3.487   6.866  30.205  1.00 31.46           C  

我只是拉着&#34; Y&#34;以及与17和18相对应的数字。

2 个答案:

答案 0 :(得分:2)

您可以使用此ES6脚本:

// Sample data
var chainIdList = ['A', 'E', 'D', 'F', 'G', 'H'];
var chainResidue = [
  {"chainId" : "A", "residueNumber" : 24},
  {"chainId" : "E", "residueNumber" : 18},
  {"chainId" : "A", "residueNumber" : 9},
  {"chainId" : "A", "residueNumber" : 15}
];

// Create the empty lists to start with, per letter
var chainIdObj = chainIdList.reduce( (obj, id) => (obj[id] = [], obj), {} );

// Populate those lists with residue numbers
var result = chainResidue.reduce( (res, obj) => (res[obj.chainId] ? res[obj.chainId].push(obj.residueNumber) : 0, res), chainIdObj); 

console.log(result);

代码说明

主要有两个阶段:

  1. 创建一个对象,该对象具有输入数组中每个字母的属性。属性值都设置为空数组(因为我们还没有处理任何内容)。
  2. chainIdList.reduce遍历输入数组,并为每个元素调用为其提供的函数。该函数的第一个参数始终是前一个调用的结果。第一次,没有先前的调用,然后它以我们提供的空对象({})作为reduce的第二个参数开始。

    传递给reduce的函数如下所示:

    (obj, id) => (obj[id] = [], obj)
    

    这实际上是2015年由EcmaScript6引入的新符号。在“较旧”的语法中,它看起来像这样:

    function (obj, id) { return obj[id] = [], obj; }
    

    函数体使用逗号运算符,与return一起它实际上等同于此代码:

     obj[id] = [];
     return obj;
    

    因此,综合起来,obj的值以{}开头,然后在每次迭代中为其定义属性。在第一次迭代之后它是

     { 'A': [] }
    

    ...并返回到reduce内部,以便它在下一次迭代中作为参数传递,等等。在最后一次迭代中返回的对象将作为整个{的返回值返回。 {1}}致电。

    现在我们reduce等于:

    chainIdObj
    1. 第二阶段用于填充上述结构中的数组。同样,迭代是{ "A": [], "E": [], "D": [], "F": [], "G": [], "H": [] } ;这次超过reduce。为chainResidue中的每个对象执行的函数是:

      chainResidue
    2. 第一个参数((res, obj) => (res[obj.chainId] ? res[obj.chainId].push(obj.residueNumber) : 0, res) )的第一个值是这次未使用res初始化,而是使用前一个阶段的结果:{}。上面的函数检查我们正在查看的对象的chainIdObj属性值是否与chainId中的条目匹配(即在res中)。如果是这样(chainIdObj),相应的?将被推送到我们刚检查过的数组。在另一种情况下(residueNumber)什么都不应该发生。但是由于三元运算符需要第三个表达式,我们只是放::无论如何,表达式的值被忽略,所以这只是一个语法填充。

      最后,逗号运算符再次用于确保0对象返回到res内部,因此我们在下一次迭代中再次获取它。最终结果是最后一次迭代的结果,并由reduce返回。它被分配到reduce

      这是在控制台中输出的东西。

      功能代码

      有些人喜欢在可能的情况下避免变量赋值,并将它们的使用限制为函数参数。使用上述元素,您可以编写如下代码:

      result

答案 1 :(得分:0)

虽然你已经有了答案,但我建议不要使用Array#reduce,因为它总是返回相同的对象而不是必需的。

// Sample data
var chainIdList = ['A', 'E', 'D', 'F', 'G', 'H'],
    chainResidue = [{ chainId: "A", residueNumber: 24 }, { chainId: "E", residueNumber: 18}, { chainId: "A", residueNumber: 9 }, { chainId: "A", residueNumber: 15 }],    
    result = Object.create(null);

chainIdList.forEach(a => result[a] = []);
chainResidue.forEach(a => result[a.chainId] && result[a.chainId].push(a.residueNumber)); 
console.log(result);