【问题标题】:Sum string arrays and subarrays in javascript without concatenating them在javascript中对字符串数组和子数组求和而不连接它们
【发布时间】:2021-08-15 21:26:10
【问题描述】:

我正在尝试将项目从一个数组“求和”到另一个数组,同时保留它们的子数组(子数组):

array1 = [         array2 = [         array3 = [
 [                  [                  [
  "A",               "1",               "A",
  "B",               "2",               "B",
  [                  [                  "1",
   "C"      +         "3"      =        "2",
  ]                  ]                  [
 ],                 ],                  "C",
 "D"                "4"                 "3"
]                  ]                    ]
                                       ],
                                       "D",
                                       "4"
                                      ]

编辑:理想情况下,最长的数组将被视为“主”数组(其值将位于最短数组之前)。 如果数组的元素个数相同,则第一个数组为主。

["a", ["b", "c"], "d"]
          +
["x", ["v", "w"], "y"]
          =
["a" "x", ["b", "c", "v", "w"], "d", "y"]


["a", "b", ["c", "d", ["e", "f"]]]
          +
[["1", ["2"]]]
          =
["a", "b", ["c", "d", "1", ["e", "f", "2"]]]

这可能吗?到目前为止,我发现的唯一建议与 .concat() 的使用有关,但是它将一个数组连接到另一个数组的末尾,并且不会合并两者:

var array1 = [["A", "B", ["C"]], "D"];
var array2 = [["1", "2", ["3"]], "4"];
console.log(array1.concat(array2)) // returns [["A", "B", ["C"]], "D", ["1", "2", ["3"]], "4"]

编辑 2: 我现在一直在以不同的方式思考这个问题,并意识到一个简单的可视化方法是这样的:

target = [
 "A",
 "B",
 [
  "C",
  "D",
  [
   "E"
  ],
 "J"
 ]
]

我想在“E”之后添加以下元素:

newelement = [
 [
  [
   "F",
   [
    "G",
    "H",
    "I"
   ]
  ]
 ]
]

结果是:

result = [
 "A",
 "B",
 [
  "C",
  "D",
  [
   "E",
   "F",
   [
    "G",
    "H",
    "I"
   ]
  ],
 "J"
 ]
]

基本上就是这样,将一个数组与另一个数组合并。

【问题讨论】:

  • 你保证有相同数量的元素吗?或者它们可以不同吗?
  • @VLAZ 他们可以区分,理想情况下最长的数组将被视为“主”数组。
  • 您需要阐明用于合并它们的规则。例如,为什么“1”在“B”之后、“D”之前和“C”之前?
  • 好的,如果在同一个索引上一个数组有一个数组,另一个数组是一个普通值,例如,["a", ["b", "c"], "d"]` 结合["x", "y", "z"],会发生什么?
  • @Janilson 是的,我认为整数/字符串优先于数组,最长的数组优先于最短的数组。这种情况下的优先级是指先添加。

标签: javascript arrays object merge


【解决方案1】:

如果我理解正确,你想连接两个数组的子部分,它们只包含非数组(元素的数量可能不同),然后递归地合并两个数组的下一个数组,然后再次将第一个逻辑应用于下一个没有数组的小节......等等。

这是实现的想法:

function deepConcat(a, b) {
    if (a.length < b.length) return deepConcat(b, a);
    let i = 0, j = 0, result = [];
    while (true) {
        while (i < a.length && !Array.isArray(a[i])) result.push(a[i++])
        while (j < b.length && !Array.isArray(b[j])) result.push(b[j++])
        if (i >= a.length || j >= b.length) break;
        result.push(deepConcat(a[i++], b[j++]));
    }
    return [...result, ...a.slice(i), ...b.slice(j)];
}

const test = (a, b) => console.log(JSON.stringify(deepConcat(a, b)));

test([["A", "B", ["C"]], "D"], [["1", "2", ["3"]], "4"]);
test(["a", ["b", "c"], "d"], ["x", ["v", "w"], "y"]);
test(["a", "b", ["c", "d", ["e", "f"]]], [["1", ["2"]]]);
test(["A","B",["C","D",["E"],"J"]], [[["F",["G","H","I"]]]]);

【讨论】:

  • 谢谢!,在看到您的解决方案之前,我已经用一个新示例编辑了帖子,并将其用作测试,我可以看到它几乎按我预期的方式工作:["A","B",["C","D",["F","E",["G","H","I"]],"J"]] 唯一的例外是“E”之前的“F”,你知道这是不是我错误添加的规则吗?
  • 将“F”放在第一位,因为在递归调用中,数组["E"] (1) 比数组["F",["G","H","I"]] (2) 短,因此第二个数组成为 main 数组(这个逻辑确实是基于你提到的一个规则)。
  • 哦,对了,有道理。仅作记录:要删除关于最长数组为主数组的规则,请注释掉条件if (a.length &lt; b.length) return deepConcat(b, a);。再次感谢 trincot!
【解决方案2】:

这样的?

array1 = [
  ["A", "B", ["C"]], "D"
]
array2 = [
  ["1", "2", ["3"]], "4"
]

array3 = [
  ["A", "B", "1", "2", ["C", "3"]], "D", "4"
]

const findFirstNonPrimitiveIndex = arr => arr.findIndex(x => !isPrimitive(x))
const takePrimitives = (arr, pos = 0) => arr.slice(0, findFirstNonPrimitiveIndex(arr))
const isPrimitive = x => typeof x !== "object"

const merge = (arr1, arr2) => {
  const [head1, ...rest1] = arr1
  const [head2, ...rest2] = arr2
  // base case
  if (rest1.length === 0)
    if (isPrimitive(head1)) return [head1, head2];
    else return [merge(head1, head2)]
  // inductive step
  if (isPrimitive(head1)) {
    const cutPoint = findFirstNonPrimitiveIndex(rest1);
    return [
      ...takePrimitives(arr1), 
      ...takePrimitives(arr2), 
      ...merge(rest1.slice(cutPoint), rest2.slice(cutPoint))
    ]
  } else {
    return [merge(head1, head2), ...merge(rest1, rest2)];
  }
}

const result = merge(array1, array2);

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

【讨论】:

  • 这似乎适用于第一个示例,但不适用于其他示例,这是公平的,因为我后来添加了它们,我不知道它们是否错误或可能是什么,无论如何,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-05-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-09
  • 2015-06-29
相关资源
最近更新 更多