将逗号分隔的字符串数组转换为不重复的数组

3

I would like to take an array of objects:

var objArr = [
    {id:1, name:'test', seenby:'user1, user2, user3'},
    {id:2, name:'test1', seenby:'user3, user4'},
    {id:3, name:'test2', seenby:'user1, user3'},
    {id:4, name:'test3', seenby:'user2'}
];

并返回所有“seenby”用户的不同数组:

var seenByArr = ['user1', 'user2', 'user3', 'user4']

我无法想出一种有效的方法(尽可能少的代码行)将其转换为一个独特值的数组。请查看我的fiddle示例:https://jsfiddle.net/ksumarine/ss3v7dgj/


过早的优化是万恶之源 -- DonaldKnuth - Michael Hobbs
同意,不幸的是这就是我要处理的数据 :/ - ksumarine
6个回答

3
我明白这个问题并没有提到Underscore,但值得一提的是Underscore.js是一个非常流行的用于操作对象和数组的库,非常适合这种情况。
下面是使用Underscore实现此功能的一大段难以阅读的单行代码:
_.unique(_.flatten(_.map(_.pluck(objArr, 'seenby'), function(seenby) { return seenby.split(', '); })))

谢谢您的回复,但我没有使用Underscore...虽然那个解决方案看起来很棒。 - ksumarine

2

使用 String.splitArray.foreach 函数的简洁解决方案:

var arr = [];
objArr.forEach(function (obj) {
        var str = obj.seenby.split(',');
        str.forEach(function (v) {
            var user = v.trim();
            if (arr.indexOf(user) === -1) arr.push(user);
        });
});

console.log(arr);
// the output:
["user1", "user2", "user3", "user4"]    

@RomanPerekhrest - 你使用了map函数,即使foreach函数也可以工作。只是想先理解map函数的使用方式。 - Nikhil Aggarwal
@nikhil,同意,我已更新我的解决方案。我只是匆忙地提供了一个快速的答案。 - RomanPerekhrest
1
如果可以的话,我会选择两个答案作为被接受的答案。谢谢RomanPerekhrest和nikhil! - ksumarine

1
使用IIFE和临时对象的纯JavaScript解决方案,用于处理项目。

var objArr = [{ id: 1, name: 'test', seenby: 'user1, user2, user3' }, { id: 2, name: 'test1', seenby: 'user3, user4' }, { id: 3, name: 'test2', seenby: 'user1, user3' }, { id: 4, name: 'test3', seenby: 'user2' }],
    result = function (array) {
        var obj = {}, r = [];
        array.forEach(function (a) {
            a.seenby.split(', ').forEach(function (b) {
                obj[b] = obj[b] || r.push(b);
            });
        });
        return r;
    }(objArr);

document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');


1
你可以尝试以下操作。
$.each(list, function(index, value) {
    $.each(value.seenby.split(","), function(i, val) {
        if (val !== undefined && val.trim() !== "" && arr.indexOf(val.trim()) == -1) {
            arr.push(val.trim());
        }
    });
});

作为参考 - https://jsfiddle.net/ss3v7dgj/1/

@ksumarine - 欢迎 - Nikhil Aggarwal

1
given = function (x) {
    return {
        do: function (f) { x = f(x); return this },
        return: function () { return x }
    }
};

r = given(objArr)
    .do(x => x.map(y => y.seenby))
    .do(x => [].concat.apply([], x))
    .do(x => x.join(', '))
    .do(x => x.split(', '))
    .do(x => x.filter((e, i) => x.indexOf(e) === i))
    .do(x => x.sort())
    .return();

我可能将来会用到这个...


1
我会使用Array.prototype.map函数,并在关联数组中去重用户。这里是有趣的部分,但你也可以在这里尝试一下:
var list = [
    {id:1, name:'test', seenby:'user1, user2, user3'},
    {id:2, name:'test1', seenby:'user3, user4'},
    {id:3, name:'test2', seenby:'user1, user3'},
    {id:4, name:'test3', seenby:'user2'}
];

var arr = [];
list.map(function(value){
        value.seenby.split(",").map(function(val){
      arr[val.trim()] = 1;
        });
});

var seenby = Object.keys(arr);

它是如何工作的?map函数将迭代所有list项,下一个map将迭代所有seenby项。然后我们通过将其用作关联数组来收集arr中的用户,从而进行去重。 最后,我们使用Object.keys函数提取所有关联数组键。
小注意点是,如果不存在map函数,则此解决方案仅适用,否则您需要自己实现它。但通常您使用的是足够新的支持它的JavaScript版本。此解决方案还具有一个好的副作用,即您实际上不需要任何外部依赖项(当然除了显示它)。 更新: 我认为按照以下方式执行更好:
var arr = list
    .reduce(function(acc, value){
        return acc.concat(value.seenby.split(",").map(function(val){
            return val.trim()
    }))},[])
    .filter(function(item, index, array) {
        return array.indexOf(item) === index
    }
)

说明:

  • 我们取出列表中的每一项,对其进行缩减...
    • 从每一项中提取seenby字段
    • 我们对该字段进行split操作
    • 我们将每个项maptrim
  • ...我们将返回的seenby数组连接到我们的累加器数组arr中(该数组初始化为空数组[]
  • 然后我们从数组中过滤掉重复项(通过检查一个项目的索引是否与当前索引相同来实现)

太好了,感谢您的精彩解释。 - ksumarine

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