使用lodash合并对象连接值

时间:2016-12-10 02:21:08

标签: javascript lodash

我正在尝试操作此示例对象数组。

[ { name: 'John Wilson',
    id: 123,
    classes: ['java', 'c++']},
  { name: 'John Wilson',
    id: 123,
    classes: 'uml'},
   { name: 'Jane Smith',
    id: 321,
    classes: 'c++'} ]

我需要做的是合并具有相同“id”的对象,连接“类”并保留一个“名称”。

结果应为:

[ { name: 'John Wilson',
    id: 123,
    classes: ['java', 'c++', 'uml']},
   { name: 'Jane Smith',
    id: 321,
    classes: 'c++'} ]

我尝试使用.merge,但它不会连接'classes'中的值,它只保留最后一个相等对象的值。

使用lodash最简单的方法是什么?

5 个答案:

答案 0 :(得分:3)

您正在寻找的功能是_.uniqWith,有一个特殊的转折,我会在一分钟内解释。

_.uniqWith_.uniq非常相似,因为它生成一个唯一的数组,但它允许您传递自己的自定义比较器函数,该函数将被调用以确定什么算作“相等”。 / p>

Sane程序员会明白这个比较器应该是无副作用的。这段代码的工作方式是破坏该规则,并使用在幕后做额外魔术的比较功能。但是,这会产生非常简洁的代码,无论您的数组中有多少这些对象都可以使用,所以我觉得违规是合理的。

我将比较器函数命名为compareAndMerge,以免隐藏其不纯的性质。它将合并两个classes数组并更新两个对象的相关属性,但前提是它们的id值相同。

function merge(people) {
  return _.uniqWith(people, compareAndMerge)
}

function compareAndMerge(first, second) {
    if (first.id === second.id) {
        first.classes = second.classes = [].concat(first.classes, second.classes)
        return true
    }
    return false
}


var people = [{
  name: 'John Wilson',
  id: 123,
  classes: ['java', 'c++']
}, {
  name: 'John Wilson',
  id: 123,
  classes: 'uml'
}, {
  name: 'Jane Smith',
  id: 321,
  classes: 'c++'
}]

console.log(merge(people))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.2/lodash.min.js"></script>

旁白:您在原始classes列表周围缺少方括号。我确保上面的代码不关心classes属性是否包含单个字符串或字符串数​​组,以防万一。

答案 1 :(得分:1)

使用ES6,您可以使用Map来保存唯一值,Array#reduce来填充它,spread operatorMap#values将其转换回数组:

&#13;
&#13;
const arr = [{"name":"John Wilson","id":123,"classes":["java","c++"]},{"name":"John Wilson","id":123,"classes":"uml"},{"name":"Jane Smith","id":321,"classes":"c++"}];

const result = [...arr.reduce((hash, { id, name, classes }) => {
  const current = hash.get(id) || { id, name, classes: [] };
  
  classes && (current.classes = current.classes.concat(classes));
  
  return hash.set(id, current);
}, new Map).values()];

console.log(result);
&#13;
&#13;
&#13;

答案 2 :(得分:0)

不确定使用lodash ...这是使用普通JS的方法:

textField(_:shouldChangeCharactersIn:replacementString:)

小提琴:https://jsfiddle.net/6zwr47mt/

答案 3 :(得分:0)

使用_.mergeWith设置合并自定义程序

_.reduce(data, function(result, item) {
    item = _.mergeWith(
        item,
        _.find(result, {id: item.id}),
        function(val, addVal) {
            return _.isArray(val) ? _.concat(val, addVal) : val;
        });
    result = _.reject(result, {id: item.id})
    return _.concat(result, item);
}, []);

答案 4 :(得分:0)

以下算法不是最好的算法,但至少我知道它的作用: - )

&#13;
&#13;
library(lubridate)

my_date <- "Thu, 21 Jan 2012 04:59:00 -0000"

# Get it into date format
my_date <- dmy_hms(my_date)

# Use convenience functions to set up the columns you wanted
data.frame(day=day(my_date), month=month(my_date), year=year(my_date),
           timestamp = my_date)
&#13;
  day month year           timestamp
1  21     1 2012 2012-01-21 04:59:00
&#13;
&#13;
&#13;