通过匹配相同的键值来合并数组中的对象

时间:2017-03-16 00:29:55

标签: javascript arrays

抱歉,如果json不完美,我试图将其输入Stackoverflow窗口......无论如何,你可以从下面看到我想要获取数组中的所有单独对象并将它们合并到第一个具有匹配url的数组。一旦它们合并,所有其他需要从阵列中删除。

Sub Delete_Rows_Based_On_Header_and_Value()
    '
    ' Delete_Rows_Based_On_Header_and_Value Macro
    '
    ' Declaration
    Dim a As Long
    Dim w As Long
    Dim vDELCOLs As Variant
    Dim vCOLNDX As Variant
    Dim vDELROWs As Variant
    Dim vROWNDX As Variant
    Dim r As Long
    Dim v As Long

    vDELCOLs = Array("status", "Status Name", "Status Processes")
    vDELROWs = Array(Array("Complete", "Pending"), Array("Completed", "Pending"), Array("Done"))

    With ActiveWorkbook
        For w = 1 To .Worksheets.Count
            With Worksheets(w)
                For a = LBound(vDELCOLs) To UBound(vDELCOLs)
                    vCOLNDX = Application.Match(vDELCOLs(a), .Rows(1), 0)
                    If Not IsError(vCOLNDX) Then
                        For r = .Cells(.Rows.Count, vCOLNDX).End(xlUp).Row To 1 Step -1
                            For v = LBound(vDELROWs(a)) To UBound(vDELROWs(a))
                                If .Cells(r, vCOLNDX).Value = vDELROWs(a)(v) Then
                                    .Rows(r).EntireRow.Delete
                                    Exit For
                                End If
                            Next
                        Next
                    End If
                Next a
            End With
        Next w
    End With
End Sub

我需要让这个数组变成...... 您可以在下面看到具有匹配网址的对象现已移至第一个匹配的对象'变体'键。之后他们不再分开了。它们基本上全部匹配在一起并合并到同一个对象中。

var myArray = [
{ 
 id: '123',
 url: 'http://foo.com/1.jpg',
 size: 7,
 qty: 1
},
{
 id: '345',
 url: 'http://foo.com/5.jpg',
 color: 'blue',
 qty: 5
},
{
 id: '678',
 url: 'http://foo.com/1.jpg',
 size: 8,
 qty: 4
}];

到目前为止,我有类似的事情:但这只是正在进行的工作。无法将其带到终点线。

var myArray = [{ 
 id: '123',
 url: 'http://foo.com/1.jpg',
 variations:[
     {
       id : '123'
       size : 7,
       qty: 1
     }, 
     {
       id : '678'
       size : 8,
       qty: 4
     }],
{
 id: '345',
 url: 'http://foo.com/5.jpg',
 color: 'blue',
 qty: 5
}];

4 个答案:

答案 0 :(得分:1)

你可以做类似的事情;我没有将id保持在顶层,因为它看起来像是重复数据。



var myArray = [
{ 
 id: '123',
 url: 'http://foo.com/1.jpg',
 size: 7,
 qty: 1
},
{
 id: '345',
 url: 'http://foo.com/5.jpg',
 color: 'blue',
 qty: 5
},
{
 id: '678',
 url: 'http://foo.com/1.jpg',
 size: 8,
 qty: 4
}];

function mergeObjects(arr)
{
  var resultArray = [];
  var urls = [];
  for(var item in arr)
  {
    var itemIndex = urls.indexOf(arr[item].url);
    if(itemIndex == -1)
    {
      urls.push(arr[item].url);
      var obj = {};
      obj.url = arr[item].url;
      obj.variations = [];
      var variationData = {};
      variationData.id = arr[item].id;
      if(arr[item].size !== undefined)
      {
        variationData.size = arr[item].size;
      }
      if(arr[item].qty !== undefined)
      {
        variationData.qty = arr[item].qty;
      }
      if(arr[item].color !== undefined)
      {
        variationData.color = arr[item].color;
      }
     
      obj.variations.push(variationData);
      resultArray.push(obj);
    }
    else
    {
      var variationData = {};
      variationData.id = arr[item].id;
      if(arr[item].size !== undefined)
      {
        variationData.size = arr[item].size;
      }
      if(arr[item].qty !== undefined)
      {
        variationData.qty = arr[item].qty;
      }
      if(arr[item].color !== undefined)
      {
        variationData.color = arr[item].color;
      }
      resultArray[itemIndex].variations.push(variationData)
    }
    
  }
  return resultArray;
}

console.log(mergeObjects(myArray));




答案 1 :(得分:0)

我认为您可以先尝试收集对象中的所有网址,以便保证唯一性,然后将其转换为数组,就像这样,

function Merge(arr) {
    var obj = {};

    for (var elem of arr) {
        if (obj[elem.url] == undefined) {
            obj[elem.url] = {
                id: elem.id,
                variations: [],
                url: elem.url
            };
        }

        obj[elem.url].variations.push(elem);
        delete elem.url;
    }

    var ans = [];
    for (var elem in obj) {
        var tmp = {
            id: obj[elem].id,
            url: elem
        };
        if(obj[elem].variations.length > 1) 
            tmp.variations = obj[elem].variations;
        else {
            tmp.color = obj[elem].variations[0].color;
            tmp.qty = obj[elem].variations[0].qty;
        }
        ans.push(tmp);
    }

    return ans;
}

答案 2 :(得分:0)

我认为更好的数据结构将由url键入。



const myArray = [{"id":"123","url":"http://foo.com/1.jpg","size":7,"qty":1},{"id":"345","url":"http://foo.com/5.jpg","color":"blue","qty":5},{"id":"678","url":"http://foo.com/1.jpg","size":8,"qty":4}]

const urlMap = myArray.reduce((byUrl, entry) => {
  const entryWithoutUrl = Object.assign({}, entry)
  delete entryWithoutUrl.url

  if (Array.isArray(byUrl[entry.url])) {
    byUrl[entry.url].push(entryWithoutUrl)
  } else {
    byUrl[entry.url] = [entryWithoutUrl]
  }
  return byUrl
}, Object.create(null))

const newArray = Object.keys(urlMap).map(url => ({
  url: url,
  variations: urlMap[url]
}))

console.info(newArray)




答案 3 :(得分:0)

在这个例子中,我已经将问题分解为两个较小的问题,以提高效率,不必遍历数组来检查url是否已经存在,然后一旦所有内容按url分组,我们将结果对象转换回一个数组,每个键都作为数组中的项目。

如果您使用函数式编程,您可以将这些函数组合在一起

compose(objectToArray, sortByUnique)('url', myArray)

var myArray = [
  { id: '123', url: 'http://foo.com/1.jpg', qty: 1, size: 7 },
  { id: '345', url: 'http://foo.com/5.jpg', qty: 5, color: 'blue' },
  { id: '678', url: 'http://foo.com/1.jpg', qty: 4, size: 8 },
  { id: '69',  url: 'http://foo.com/1.jpg', qty: 4, size: 8 }
]

function sortByUnique(unique, array) {
  // group array by unique key into an object
  return array.reduce((acc, x) => {
    let key = x[unique]
    delete x[unique]
    if (acc[key]) {
      if (!acc[key].variations) {
        let old = acc[key]
        acc[key] = {
          variations: [old, x]
        }
      }
      else {
        acc[key].variations.push(x)
      }
    }
    else {
      acc[key] = x
    }
    return acc
  }, {})
}

function objectToArray(obj) {
  return Object.keys(obj).map(
    k => Object.assign(
      { url: k },
      obj[k]
    ))
}

console.log(
  objectToArray(sortByUnique('url', myArray))
)