使用来自 javascript 的两个数组的不同值创建 objects 的数组
Create array of objects using distinct values from two arrays with javascript
我的问题有点复杂。我有两个数据数组:
var arr = [
{title: "foo", namesIndices: [0,1]},
{title: "bar", namesIndices: [2]},
{title: "baz", namesIndices: [3,4]}
];
var names = [
{name: "John", website: "someUrl"},
{name: "Mike", website: "someUrl"},
{name: "Jane", website: "someUrl"},
{name: "Ali", website: "someUrl"},
{name: "Robert", website: "someUrl"}
];
其中 namesIndices 将引用 names 数组中的索引,该索引将与该人及其头衔相对应。为了将此人的姓名和网站与正确的标题相匹配以构成此数组:
var person = [
{name: "John", title: "foo", website: "someUrl"},
{name: "Mike", title: "foo", website: "someUrl"},
{name: "Jane", title: "bar", website: "someUrl"},
{name: "Ali", title: "baz", website: "someUrl"},
{name: "Robert", title: "baz", website: "someUrl"}
];
我必须循环遍历第一个数组,然后循环遍历 arr.namesIndices:
var person = [];
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr[i].namesIndices.length; j++) {
var personObj = {};
personObj.title= arr[i].title;
personObj.name = names[arr[i].namesIndices[j]].name;
personObj.website= names[arr[i].namesIndices[j]].website;
person.push(personObj);
}
}
有没有没有嵌套循环的方法来做到这一点?
仍然需要两个循环,但它们现在不是嵌套的:
var arr = [
{title: "foo", namesIndices: [0, 1]},
{title: "bar", namesIndices: [2]},
{title: "baz", namesIndices: [3, 4, 5]}
];
var names = [
{name: "John", website: "someUrl"},
{name: "Mike", website: "someUrl"},
{name: "Jane", website: "someUrl"},
{name: "Ali", website: "someUrl"},
{name: "Robert", website: "someUrl"}
];
var people = [];
var makePeople = function(title, indices){
for(var i = 0; i < indices.length; i++){
people.push({
name: names[indices[i]].name,
title: title,
website: names[indices[i]].website
});
}
}
for(var i = 0; i < arr.length; i++){
makePeople(arr[i].title, arr[i].nameIndices);
}
虽然它并没有完全缩短,但它的作用基本相同。
如果您愿意,可以使用 reduce()
和 map()
来完全避免显式循环。
var arr = [
{title: "foo", namesIndices: [0,1]},
{title: "bar", namesIndices: [2]},
{title: "baz", namesIndices: [3,4]}
];
var names = [
{name: "John", website: "someUrl"},
{name: "Mike", website: "someUrl"},
{name: "Jane", website: "someUrl"},
{name: "Ali", website: "someUrl"},
{name: "Robert", website: "someUrl"}
];
var person = arr.reduce(function (accumulator, titleAndIndices, arrIndex) {
var newEntries = titleAndIndices.namesIndices.map(function (index) {
var rv = names[index];
rv.title = arr[arrIndex].title;
return rv;
});
return accumulator.concat(newEntries);
}, []);
console.log(person);
Is there a way to do this without nested loops?
没有。 没有错。您的数据采用嵌套格式,因此使用嵌套控制结构使用它是完全自然的。这仍然具有 O(n)
复杂性,其中 n
是数据量(n = al * ni
具有 arr
长度和每个项目的平均 namesIndices
数量)
如果您愿意销毁 arr
数组并重新调整 names
数组的用途(正如公认的答案那样),您可以通过简单的递归函数实现您的目标。我认为这是无循环的,因为它不使用循环语法。我认为这已经接近于无循环,除了为每个数组索引硬编码一个单独的进程。
递归函数
var person = (function func(obj) {
names[obj.namesIndices.pop()].title = obj.title;
return obj.namesIndices.length ? func(obj) : arr.length ? func(arr.pop()) : names;
})(arr.pop());
如果让函数跟踪数组索引而不是使用 pop(),则可以保留原始数组,但我没有耐心那样做:)。
如果您可以容忍单个循环,那么您可以用确定递增哪个计数器的条件语句替换嵌套循环。与前面的示例不同,这个示例不会改变原始数组。
单循环
var person = [];
for(var a = arr.length - 1, n = arr[a].namesIndices.length - 1, obj, i;;) {
i = arr[a].namesIndices[n];
obj = names[i];
person[i] = {name: obj.name, website: obj.website, title: arr[a].title};
if(n) n--;
else if(a) n = arr[--a].namesIndices.length - 1;
else break;
}
我还没有正确测试这两种技术的性能,但我相信它至少可以与嵌套循环的性能相媲美,并且比任何涉及数组迭代方法的解决方案都要好 reduce
, map
, forEach
, 等等
我的问题有点复杂。我有两个数据数组:
var arr = [
{title: "foo", namesIndices: [0,1]},
{title: "bar", namesIndices: [2]},
{title: "baz", namesIndices: [3,4]}
];
var names = [
{name: "John", website: "someUrl"},
{name: "Mike", website: "someUrl"},
{name: "Jane", website: "someUrl"},
{name: "Ali", website: "someUrl"},
{name: "Robert", website: "someUrl"}
];
其中 namesIndices 将引用 names 数组中的索引,该索引将与该人及其头衔相对应。为了将此人的姓名和网站与正确的标题相匹配以构成此数组:
var person = [
{name: "John", title: "foo", website: "someUrl"},
{name: "Mike", title: "foo", website: "someUrl"},
{name: "Jane", title: "bar", website: "someUrl"},
{name: "Ali", title: "baz", website: "someUrl"},
{name: "Robert", title: "baz", website: "someUrl"}
];
我必须循环遍历第一个数组,然后循环遍历 arr.namesIndices:
var person = [];
for (var i = 0; i < arr.length; i++) {
for (var j = 0; j < arr[i].namesIndices.length; j++) {
var personObj = {};
personObj.title= arr[i].title;
personObj.name = names[arr[i].namesIndices[j]].name;
personObj.website= names[arr[i].namesIndices[j]].website;
person.push(personObj);
}
}
有没有没有嵌套循环的方法来做到这一点?
仍然需要两个循环,但它们现在不是嵌套的:
var arr = [
{title: "foo", namesIndices: [0, 1]},
{title: "bar", namesIndices: [2]},
{title: "baz", namesIndices: [3, 4, 5]}
];
var names = [
{name: "John", website: "someUrl"},
{name: "Mike", website: "someUrl"},
{name: "Jane", website: "someUrl"},
{name: "Ali", website: "someUrl"},
{name: "Robert", website: "someUrl"}
];
var people = [];
var makePeople = function(title, indices){
for(var i = 0; i < indices.length; i++){
people.push({
name: names[indices[i]].name,
title: title,
website: names[indices[i]].website
});
}
}
for(var i = 0; i < arr.length; i++){
makePeople(arr[i].title, arr[i].nameIndices);
}
虽然它并没有完全缩短,但它的作用基本相同。
如果您愿意,可以使用 reduce()
和 map()
来完全避免显式循环。
var arr = [
{title: "foo", namesIndices: [0,1]},
{title: "bar", namesIndices: [2]},
{title: "baz", namesIndices: [3,4]}
];
var names = [
{name: "John", website: "someUrl"},
{name: "Mike", website: "someUrl"},
{name: "Jane", website: "someUrl"},
{name: "Ali", website: "someUrl"},
{name: "Robert", website: "someUrl"}
];
var person = arr.reduce(function (accumulator, titleAndIndices, arrIndex) {
var newEntries = titleAndIndices.namesIndices.map(function (index) {
var rv = names[index];
rv.title = arr[arrIndex].title;
return rv;
});
return accumulator.concat(newEntries);
}, []);
console.log(person);
Is there a way to do this without nested loops?
没有。 没有错。您的数据采用嵌套格式,因此使用嵌套控制结构使用它是完全自然的。这仍然具有 O(n)
复杂性,其中 n
是数据量(n = al * ni
具有 arr
长度和每个项目的平均 namesIndices
数量)
如果您愿意销毁 arr
数组并重新调整 names
数组的用途(正如公认的答案那样),您可以通过简单的递归函数实现您的目标。我认为这是无循环的,因为它不使用循环语法。我认为这已经接近于无循环,除了为每个数组索引硬编码一个单独的进程。
递归函数
var person = (function func(obj) {
names[obj.namesIndices.pop()].title = obj.title;
return obj.namesIndices.length ? func(obj) : arr.length ? func(arr.pop()) : names;
})(arr.pop());
如果让函数跟踪数组索引而不是使用 pop(),则可以保留原始数组,但我没有耐心那样做:)。
如果您可以容忍单个循环,那么您可以用确定递增哪个计数器的条件语句替换嵌套循环。与前面的示例不同,这个示例不会改变原始数组。
单循环
var person = [];
for(var a = arr.length - 1, n = arr[a].namesIndices.length - 1, obj, i;;) {
i = arr[a].namesIndices[n];
obj = names[i];
person[i] = {name: obj.name, website: obj.website, title: arr[a].title};
if(n) n--;
else if(a) n = arr[--a].namesIndices.length - 1;
else break;
}
我还没有正确测试这两种技术的性能,但我相信它至少可以与嵌套循环的性能相媲美,并且比任何涉及数组迭代方法的解决方案都要好 reduce
, map
, forEach
, 等等