将数组按奇偶索引转换为对象

9
我正在尝试根据数组的索引是奇数还是偶数将数组转换为对象。
例如:
输入: ``` ["name", "Tom", "age", 20] ```
输出: ``` { "name": "tom","age": 20 } ```
可以使用JavaScript的基本函数,如forEach、map和filter来实现。但我想要更简单的代码。
因此,我查阅了underscore.js文档,但没有找到一个好的方法。 有没有更简单的解决方法?

请告诉我是否有任何模块可以简单地解决这个问题。(类似于underscore.js) - soy
6个回答

5

有趣的问题,我的看法是:

简单而高效的for循环:

const simpleArray = ["name", "Tom", "age", 20];

// Modifying the Array object
Array.prototype.toObject = function() {
    let r = {};

    for(let i = 0; i < this.length; i += 2) {
        let key = this[i], value = this[i + 1];
        r[key] = value;
    }

    return r;
}

// Or as a function
const toObject = arr => {
    let r = {};

    for(let i = 0; i < arr.length; i += 2) {
        let key = arr[i], value = arr[i + 1];
        r[key] = value;
    }

    return r;
}

const simpleObjectOne = simpleArray.toObject(); // First method
const simpleObjectTwo = toObject(simpleArray); // Second method

4

您可以使用Array#forEach和对索引的检查,如果是奇数索引,则将元素分配给上一个条目的键。

var array =  ["name", "Tom", "age", 20],
    object = {};

array.forEach(function (a, i, aa) {
    if (i & 1) {
        object[aa[i - 1]] = a;
    }
});

console.log(object);

这与Array#reduce相同。

var array =  ["name", "Tom", "age", 20],
    object = array.reduce(function (r, a, i, aa) {
        if (i & 1) {
            r[aa[i - 1]] = a;
        }
        return r;
    }, {});

console.log(object);


当然可以,但他说他不想使用 forEach 等方法。 - user663031
这种方式比在数组外部硬编码引用更安全。这种风格使回调函数也可以重复使用于其他数组。 - Nina Scholz
@NinaScholz 你能解释一下(i & 1)是如何工作的吗?以及为什么你要这样使用它? - U Rogel
1
@cowCrazy,你所看到的是一个按位与&。任何操作数都会被转换成一个整数值(给定的值),此操作执行一个AND运算,返回一个新的数字,在这种情况下,给定的数字是一个32位的正整数值,通过AND运算,仅返回最后一位。 - Nina Scholz
1
@cowCrazy,如果数字是奇数,则为1,否则为零,这是一个真值/假值的值,非常适合作为条件。 - Nina Scholz
显示剩余3条评论

2

Underscore解决方案:


output = _.object(..._.partition(input, (_, i) => !(i % 2)))
_.partition会将数组分成[['name', 'age'], ["tom", "20"]]。换句话说,它返回一个包含两个子数组的数组--在这种情况下,一个键数组和一个值数组。_.object接受一个键数组和一个值数组作为参数,因此我们使用...将由_.partition返回的子数组作为两个参数传递给它。
如果您喜欢非常功能性、语义化的代码:
const even = i => !(i % 2);
const index = fn => (_, i) => fn(i);

output = _.object(..._.partition(input, index(even)))

递归解决方案:

function arrayToObject([prop, value, ...rest], result = {}) {
  return prop ? arrayToObject(rest, Object.assign(result, {[prop]: value})) : result;
}

迭代解决方案:

function arrayToObject(arr) {
  const result = {};
  while (arr.length) result[arr.shift()] = arr.shift();
  return result;
}

1

你也可以使用 reduce

var arr = ["name", "Tom", "age", 20],
    obj = arr.reduce((p,c,i,a) => (i%2 ? p[a[i-1]] = c : p[c],p),{});
console.log(obj);

对于这个操作,如下所示:;

冒号后的 p[c] 的意义/效果是什么? - user663031

1
var input = ["name", "Tom", "age", 20] ;
var output = {}
input.forEach((x, i, arr) => {
  if (i % 2 === 0) output[x] = arr[i+1];
});
console.log(output); //{ name: 'Tom', age: 20 }

抱歉,我是JavaScript的初学者.. TT .. arr 等于 input 吗? 如果是的话,为什么 forEach 的回调函数使用 arr 作为参数? - soy
是的,回调函数需要三个参数: 元素值, 元素索引, 以及正在遍历的数组。 - kevin ternet
条件 i < input.length - 1 不是多余的吗? - user663031
当然可以,因为我在一个偶数长度的数组中针对偶数索引。我刚刚删除了这个无关条件。谢谢。 - kevin ternet

0
一个简单的for循环。
var arr = ["name", "Tom", "age", 20, "address"];
var obj = {};
for (var i = 0; i < arr.length; i+=2){
    //First iteration: assign obj["name"] to "Tom"
    //Second iteration: assign obj["age"] to 20
    //Third iteration: assign obj["address"] to "" because arr[5] does not exist
    obj[arr[i]] = arr[i+1] || "";
}

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