【问题标题】:Merging two multidimensional arrays based on matching keys?基于匹配键合并两个多维数组?
【发布时间】:2017-02-24 19:25:47
【问题描述】:

所以目前我正在生成应该组合在一起形成以下 JSON 的记录:

{
  "Monday": [{
      "Index": "1",
      "To": "200",
      "From": "1200"
    },
    {
      "Index": "2",
      "To": "1300",
      "From": "1400"
    }
  ],
  "Tuesday": [{
      "Index": "1",
      "To": "100",
      "From": "200"
    },
    {
      "Index": "2",
      "To": "1000",
      "From": "1200"
    },
    {
      "Index": "3",
      "To": "1300",
      "From": "1500"
    }
  ]
}

但目前,输出看起来更像这样:

如您所见,正在创建两条共享相同“索引”值的记录——这主要是因为我还没有弄清楚如何使用where index = <index> insert 来处理查找具有匹配索引的记录并添加属性给它。

目前,代码如下-

var controlsJson;
//Assume two loops are running through different sets of values for "type". setting them to "To" and "From" pragmatically.
//Array building
if (controlsJson == null) {
  controlsJson = [];
}
if (controlsJson[date] == null) {
  controlsJson[date] = [];
}
var pusher = [];
pusher["Index"] = index;
pusher[type] = time;
controlsJson[date].push(pusher);

除了解决匹配索引键的问题之外,我还有其他方法可以改进吗?

【问题讨论】:

  • 发布你想要的输出!
  • ^^ 和测试表单中的输入对象!
  • 所需的输出是我发布的第一个 JSON。当前的输出就是图中的那个。
  • 看问题的右边。相关部分中链接了许多问题。其中至少有一个可能会回答您的问题。
  • 它们都没有像我在这种情况下那样动态地使用属性。

标签: javascript arrays json multidimensional-array


【解决方案1】:

如果您改为以以下格式表示您的数据,这将更容易遍历:

let state = {
  Monday: {
    1: {
      To: 200,
      From: 1200
    },
    2: {
      To: 1300,
      From: 1400
    }
  },
  Tuesday: {
    1: {
      To: 100,
      From: 200
    },
    2: {
      To: 1000,
      From: 1200
    },
    3: {
      To: 1300,
      From: 1500
    }
  }
}

state = { ...state, Tuesday: { ...state.Tuesday, 2: { To: 1500, From: 1400 } } }

console.log(state)

如果您不关心不变性,以下方法也可以:

let state = {
  Monday: {
    1: {
      To: 200,
      From: 1200
    },
    2: {
      To: 1300,
      From: 1400
    }
  },
  Tuesday: {
    1: {
      To: 100,
      From: 200
    },
    2: {
      To: 1000,
      From: 1200
    },
    3: {
      To: 1300,
      From: 1500
    }
  }
}

state["Tuesday"][2] = { To: 1500, From: 1400 };

console.log(state)

【讨论】:

  • 哈哈,这其实是我原本打算这样表示的,但我觉得如果我最终得到非标准索引就会有问题。会吗?
  • 从合并数据的角度来看,使用上述索引对象比处理数组要容易得多。如果你用一个数组来做,我根本不会使用索引(而是通过序数引用)。要考虑的另一件事是您是否应该遵守不可变状态更新。上面的示例将创建一个全新的对象并将您以前的状态合并到它,而不是改变现有的状态。
  • @Bitz 如果您不想以不可变的方式工作,我添加了一个更简单的示例。
  • @Bitz 回答您的评论,这适用于任何索引(字符串、数字等),它将它们存储为哈希表,基本上在索引上运行 toString() 并使用该键反对。
  • 我认为您是对的,我将采用这种方法,因为它似乎可以显着简化添加数据。谢谢你。我会接受这个作为答案并提供源代码来实现这种方法。
【解决方案2】:

正如 cchamberlain 所指出的,我处理索引的方式比真正需要的要复杂得多。

我将我的代码修改为以下内容并使用不可变的方法(我认为这就是所谓的),只需使用索引就可以实用地添加记录!

//Array building
if (controlsJson == null) {
    controlsJson = [];
}
if (controlsJson[date] == null) {
    controlsJson[date] = [];
}

if (controlsJson[date][index] == null) {
    controlsJson[date][index] = [];
}

controlsJson[date][index][type] = time;
}

另外请注意,如果您希望使用 JSON.Stringify,您需要将 = [] 更改为 = {}

再一次——如果你摔倒了,我可以进一步改进这段代码,请告诉我。

【讨论】:

  • 只是为了修正一些命名法,这实际上不是一种不可变的方法,但如果您不以不变性为目标,它看起来不错。这不是一成不变的,因为您直接在 [date][index][type] 路径上改变您的对象。与您尝试的原始方法相比,这种策略看起来确实更容易使用。
  • 不确定我是否遵循,数组是有效的 JSON 结构,因此 JSON.stringify 应该同时处理 [](数组)和 {}(对象)。
  • 我也没有,但显然这很重要。我得到了一个带有[] 的空数组,但是当我使用{} stackoverflow.com/questions/7259728/json-stringify-returning 时得到了正确的响应@
  • 啊,如果您将结构声明为数组,然后为其分配字符串属性,它们将不会显示在结果中,因为数组也可以像哈希表一样工作,所以这可能就是发生在您身上的事情.
  • 我想就是这样-我尝试通过console.log 将其视为字符串,然后设置隐藏字段的.val(),这两者都会导致它。感谢您对张伯伦的所有帮助!
【解决方案3】:

如果每天的索引都从 0 开始,这个小 sn-p 应该可以解决问题:

// your object that you start with
var days = {
    'Monday': [
        {Index: 0, Start: 330},
        {Index: 0, End: 1330},
        {Index: 1, Start: 330},
        {Index: 1, End: 1330},
        {Index: 2, Start: 330},
        {Index: 2, End: 1330},
    ],
    'Tuesday': [
        {Index: 0, Start: 330},
        {Index: 0, End: 1330},
        {Index: 1, Start: 330},
        {Index: 1, End: 1330},
        {Index: 2, Start: 330},
        {Index: 2, End: 1330},
        {Index: 3, Start: 330},
        {Index: 3, End: 1330},
    ],
};

// create an array of indexes. For each index, filter days by that Index,
// then pass those to Object.assign to merge the 2 items together.
var i, dayMaxIndex;
for (i in days) {
    if (days.hasOwnProperty(i)) {
        dayMaxIndex = Math.max.apply(null, days[i].map(function(d) { return d.Index; }));
        days[i] = Array.from({length: dayMaxIndex+1}, (v, i) => i).map(function(d) {
            return Object.assign.apply(null, days[i].filter(function(day) {
                return day.Index == d;
            }));
        });
    }
}
console.log(days);

您可以准备更多关于 Object.assign here

我发现这篇文章有点令人困惑:

Array.from({length: dayMaxIndex+1}, (v, i) => i)

它生成一个序列号数组,从 0 开始,到 dayMaxIndex 结束。 Here's 我在哪里找到了这个例子。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    相关资源
    最近更新 更多