基于自增键的Javascript对象数组合并

3
这是我所拥有的:我想要合并那些以 "path-"+i 开头的键值对。同时,我希望在最终结果中删除这些键名中的 "path-i"。
  var arr = [
  {
    "key": "path-0-mp4",
    "value": [
      "media/video/01.mp4",
      "media/video/01_hd.mp4"
    ]
  },
  {
    "key": "path-0-quality",
    "value": [
      "720p",
      "1080p"
    ]
  },
  {
    "key": "path-1-mp4",
    "value": [
      "media/video/02.mp4",
      "media/video/02_hd.mp4"
    ]
  },
  {
    "key": "path-1-quality",
    "value": [
      "SD",
      "HD"
    ]
  }

]

这是一个期望的结果:

 var arr = [
        [
              {
                "mp4": "media/video/01.mp4",
                "quality": "720p"
              },
              {
                "mp4": "media/video/01_hd.mp4",
                "quality": "1080p"
              },
        ],
        [
              {
                "mp4": "media/video/02.mp4",
                "quality": "SD"
              },
              {
                "mp4": "media/video/02_hd.mp4",
                "quality": "HD"
              },
        ],
]

我开始做某件事,但还远远不够:
var key, new_key, value,j=0, z=0, parr = [], obj;
for(var i = 0;i<a.length;i++){
    console.log('item:' ,a[i])
    key = a[i].key, value = a[i].value
    if(key.indexOf('path-'+j.toString()) > -1){
        new_key = key.substr(key.lastIndexOf('-')+1)
        console.log(key, new_key, value)
        for(var z = 0;z<value.length;z++){
            parr.push({[new_key]: value[z] })
        }
    }
}

console.log(parr)

[
  {
    "mp4": "media/video/01.mp4"
  },
  {
    "mp4": "media/video/01_hd.mp4"
  },
  {
    "quality": "720p"
  },
  {
    "quality": "1080p"
  }
]

编辑:

数组可能潜在地拥有需要以相同方式进行分组的不同键,例如:

    var arr = [
  {
    "key": "path-0-mp4",
    "value": [
      "media/video/01.mp4",
      "media/video/01_hd.mp4"
    ]
  },
  {
    "key": "path-0-quality",
    "value": [
      "720p",
      "1080p"
    ]
  },
  {
    "key": "path-1-mp4",
    "value": [
      "media/video/02.mp4",
      "media/video/02_hd.mp4"
    ]
  },
  {
    "key": "path-1-quality",
    "value": [
      "SD",
      "HD"
    ]
  },
  {
    "key": "subtitle-0-label",
    "value": [
      "English",
      "German",
      "Spanish"
    ]
  },
  {
    "key": "subtitle-0-src",
    "value": [
      "data/subtitles/sintel-en.vtt",
      "data/subtitles/sintel-de.vtt",
      "data/subtitles/sintel-es.vtt"
    ]
  },
  {
    "key": "subtitle-1-label",
    "value": [
      "German",
      "Spanish"
    ]
  },
  {
    "key": "subtitle-1-src",
    "value": [
      "data/subtitles/tumblr-de.vtt",
      "data/subtitles/tumblr-es.vtt"
    ]
  }
]

这是一个期望的结果(为每个不同的键创建新数组):
 var arr = [
        [
              {
                "mp4": "media/video/01.mp4",
                "quality": "720p"
              },
              {
                "mp4": "media/video/01_hd.mp4",
                "quality": "1080p"
              },
        ],
        [
              {
                "mp4": "media/video/02.mp4",
                "quality": "SD"
              },
              {
                "mp4": "media/video/02_hd.mp4",
                "quality": "HD"
              },
        ],
],
arr2 = [        
    [
        {
            "label": "English",
            "src": "data/subtitles/sintel-en.vtt",
        },
        {
            "label": "German",
            "src": "data/subtitles/sintel-de.vtt"
        },
        {
            "label": "Spanish",
            "src": "data/subtitles/sintel-es.vtt"
        }
    ],
    [
        {
            "label": "Spanish",
            "src": "data/subtitles/tumblr-es.vtt",
        },
        {
            "label": "German",
            "src": "data/subtitles/tumblr-de.vtt"
        }
    ]
 ]
4个回答

3
你可以拆分key属性,忽略第一个path,将其余部分作为索引和键。然后创建一个新数组(如果不存在),并赋值。

var data = [{ key: "path-0-mp4", value: ["media/video/01.mp4", "media/video/01_hd.mp4"] }, { key: "path-0-quality", value: ["720p", "1080p"] }, { key: "path-1-mp4", value: ["media/video/02.mp4", "media/video/02_hd.mp4"] }, { key: "path-1-quality", value: ["SD", "HD"] }],
    result = data.reduce((r, { key, value }) => {
        let [, i, k] = key.split('-');
        r[i] = r[i] || [];
        value.forEach((v, j) => (r[i][j] = r[i][j] || {})[k] = v);
        return r;
    }, []);

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

如果您想按 key 的第一部分进行分组,可以取一个具有此组作为键的对象,并将其余部分分配如上。

var data = [{ key: "path-0-mp4", value: ["media/video/01.mp4", "media/video/01_hd.mp4"] }, { key: "path-0-quality", value: ["720p", "1080p"] }, { key: "path-1-mp4", value: ["media/video/02.mp4", "media/video/02_hd.mp4"] }, { key: "path-1-quality", value: ["SD", "HD"] }, { key: "subtitle-0-label", value: ["English", "German", "Spanish"] }, { key: "subtitle-0-src", value: ["data/subtitles/sintel-en.vtt", "data/subtitles/sintel-de.vtt", "data/subtitles/sintel-es.vtt"] }, { key: "subtitle-1-label", value: ["German", "Spanish"] }, { key: "subtitle-1-src", value: ["data/subtitles/tumblr-de.vtt", "data/subtitles/tumblr-es.vtt"] }],
    result = data.reduce((r, { key, value }) => {
        let [group, i, k] = key.split('-');
        if (!r[group]) r[group] = [];
        if (!r[group][i]) r[group][i] = [];
        value.forEach((v, j) => {
            if (!r[group][i][j]) r[group][i][j] = {};
            r[group][i][j][k] = v;
        });
        return r;
    }, {});

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


这个解决方案适用于任何密钥的结尾。但是当您使用单个字母变量时,它非常难以阅读。 - mplungjan
@mplungjan,所需的结果具有嵌套数组。 - Nina Scholz
这个程序能否接受一个键值来对不同的键进行分组或区分?如果我的数组中有几个不同的键需要进行分组怎么办?我已经编辑了我的问题。 - Toniq
你的编辑没有达到预期的结果。为什么一个地方用了"path",而另一个地方用了不同的单词?应该怎么处理呢?(也许最好保留原来的问题,并针对这个具体的问题提出一个新问题 - 以及你的尝试,可能会更好一些。) - Nina Scholz
抱歉,我已添加所需结果。基本上我想要相同的东西,但是针对不同的键组。我考虑将其从原始数组中分离,并针对每个组(路径-、字幕-)调用此函数。除非有更好的方法? - Toniq
@Toniq,请查看编辑后的内容,第二部分。你可以将该组作为结果返回。 - Nina Scholz

1

我是一个新手,对编程不太了解,这样做正确吗?

const a = [{ "key": "path-0-mp4", "value": [ "media/video/01.mp4", "media/video/01_hd.mp4" ] }, { "key": "path-0-quality", "value": [ "720p", "1080p" ] }, { "key": "path-1-mp4", "value": [ "media/video/02.mp4", "media/video/02_hd.mp4" ] }, { "key": "path-1-quality", "value": [ "SD", "HD" ] } ];

var resp = [];
for (let i = 0; i < a.length; i++) {
  var inst = a[i];
  var key = inst["key"];
  for (let j = 0; j < inst.value.length; j++) {
    var index = key.split("-")[1];
    var keyinst = key.split("-")[2];
    if (!resp[index]) {
      resp[index] = [];
    }
    if (!resp[index][j]) {
      resp[index][j] = {};
    }
    resp[index][j][keyinst] = inst.value[j];
  }
}
console.log(resp);


我认为Nina的方法更加优雅,但你的方法肯定能够工作并最终实现相同的功能。不过,我会将“var”替换为“let”,以便更好地控制变量的作用域。 - wschopohl
谢谢,我觉得这更容易理解了。 感谢您的回复,先生。 - morphen

1

我觉得这篇更容易读懂和掌握

如果你使用reduce,你可以保存一个任务

const arr = [{ "key": "path-0-mp4", "value": [ "media/video/01.mp4", "media/video/01_hd.mp4" ] }, { "key": "path-0-quality", "value": [ "720p", "1080p" ] }, { "key": "path-1-mp4", "value": [ "media/video/02.mp4", "media/video/02_hd.mp4" ] }, { "key": "path-1-quality", "value": [ "SD", "HD" ] } ];

newArr = [];
arr.filter(item => item.key.endsWith("mp4"))
     .forEach(item => item.value
       .forEach((val, i) => newArr.push({
          "mp4": val, 
      "quality": arr.find(qItem => qItem.key === item.key.replace("mp4", "quality")).value[i]}
     )
   )
 )

console.log(newArr)

这是Nina的未混淆版本。

var data = [{ key: "path-0-mp4", value: ["media/video/01.mp4", "media/video/01_hd.mp4"] }, { key: "path-0-quality", value: ["720p", "1080p"] }, { key: "path-1-mp4", value: ["media/video/02.mp4", "media/video/02_hd.mp4"] }, { key: "path-1-quality", value: ["SD", "HD"] }],

  result = data.reduce((resultArray, { key, value }) => {
        let [, idx, suffix] = key.split('-');
        resultArray[idx] = resultArray[idx] || [];
        value.forEach((val, i) => (resultArray[idx][i] = resultArray[idx][i] || {})[suffix] = val);
        return resultArray;
    }, []);

console.log(result);


0

我在这里做的唯一奇怪的事情是使用一个对象作为查找表来帮助处理速度复杂性。如果您有任何问题,请让我知道。

const arr = [{ "key": "path-0-mp4", "value": [ "media/video/01.mp4", "media/video/01_hd.mp4" ] }, { "key": "path-0-quality", "value": [ "720p", "1080p" ] }, { "key": "path-1-mp4", "value": [ "media/video/02.mp4", "media/video/02_hd.mp4" ] }, { "key": "path-1-quality", "value": [ "SD", "HD" ] } ];


const result = arr.reduce((table, item) => {
  // Getting "path-1" from "path-1-quality" 
  const pathValues = item.key.split('-');
  const pathValue = pathValues[0] + '-' + pathValues[1];
  // Getting "quality" from "path-1-quality" 
  const key = pathValues[2];
  
  // Get Index from table if already registered paths
  let tIndex = table.indexLookup[pathValue]; 
  
  // If there is no registered index register one
  if (tIndex === undefined) {
    // reassign index to new location
    tIndex = table.result.length;
    // register the index
    table.indexLookup[pathValue] = tIndex;
    table.result.push([]);
  }
  
  // Assign values
  item.value.forEach((value, i) => {
   const arr = table.result[tIndex] || [];
    arr[i] = arr[i] || {}
    arr[i][key] = value;
    table.result[tIndex] = arr;
  })
  return table
}, {
  indexLookup : {},
  result: []
}).result


console.log(result)


抱歉,我似乎错了。似乎不再需要使用“Flat”。 - mplungjan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接