这不是最优雅的代码,但我认为如果需要,遵循/破解非常简单。允许INNER、LEFT和RIGHT连接。
您只需将函数复制并粘贴到代码中即可获得正确的输出。示例位于底部
function remove_item_from_list(list_, remove_item, all = true) {
/*
Removes all occurrences of remove_item from list_
*/
for (var i = list_.length; i--;) {
if (list_[i] === remove_item) {
list_.splice(i, 1);
}
}
return list_
}
function add_null_keys(dict_, keys_to_add){
/*
This function will add the keys in the keys_to_add list to the dict_ object with the vall null
ex:
dict_ = {'key_1': 1, 'key_2': 2}
keys_to_add = ['a', 'b', 'c']
output:
{'key_1': 1, 'key_2': 2, 'a': NULL, 'b': NULL', 'c':'NULL'}
*/
//get the current keys in the dict
var current_keys = Object.keys(dict_)
for (index in keys_to_add){
key = keys_to_add[index]
//if the dict doesnt have the key add the key as null
if(current_keys.includes(key) === false){
dict_[key] = null
}
}
return dict_
}
function merge2(dict_1, dict_2, on, how_join){
/*
This function is where the actual comparison happens to see if two dictionaries share the same key
We loop through the on_list to see if the various keys that we are joining on between the two dicts match.
If all the keys match we combine the dictionaries.
If the keys do not match and it is an inner join, an undefined object gets returned
If the keys do not match and it is NOT an inner join, we add all the key values of the second dictionary as null to the first dictionary and return those
*/
var join_dicts = true
//loop through the join on key
for (index in on){
join_key = on[index]
//if one of the join keys dont match, then we arent joining the dictionaries
if (dict_1[join_key] != dict_2[join_key]){
join_dicts = false
break
}
}
//check to see if we are still joining the dictionaries
if (join_dicts === true){
return Object.assign({}, dict_1, dict_2);
}
else{
if (how_join !== 'inner'){
//need to add null keys to dict_1, which is acting as the main side of the join
var temp = add_null_keys(dict_1, Object.keys(dict_2))
return temp
}
}
}
function dict_merge_loop_though(left_dict, right_dict, on, how_join){
/*
This function loops through the left_dict and compares everything in it to the right_dict
it determines if a join happens, what the join is and returns the information
Figuring out the left/right joins were difficult. I had to add a base_level dict to determine if there was no join
or if there was a join...its complicated to explain
*/
var master_list = []
var index = 0
//need to loop through what we are joining on
while(index < left_dict.length){
//grab the left dictionary
left_dict_ = left_dict[index]
var index2 = 0
//necessary for left/right join
var remove_val = add_null_keys(left_dict_, Object.keys(right_dict[index2]))
var temp_list = [remove_val]
while (index2 < right_dict.length){
//get the right dictionary so we can compete each dictionary to each other
right_dict_ = right_dict[index2]
//inner join the two dicts
if (how_join === 'inner'){
var temp_val = merge2(left_dict_, right_dict_, on, how_join)
//if whats returned is a dict, add it to the master list
if (temp_val != undefined){
master_list.push(temp_val)
}
}
//means we are right/left joining
else{
//left join the two dicts
if (how_join === 'left'){
var temp_val = merge2(left_dict_, right_dict_, on, how_join)
}
//right join the two dicts
else if (how_join === 'right'){
var temp_val = merge2(right_dict_, left_dict_, on, how_join)
}
temp_list.push(temp_val)
}
//increment this guy
index2++
}
//Logic for left/right joins to for what to add to master list
if (how_join !== 'inner'){
// remove the remove val from the list. All that remains is what should be added
//to the master return list. If the length of the list is 0 it means that there was no
//join and that we should add the remove val (with the extra keys being null) to the master
//return list
temp_list = remove_item_from_list(temp_list, remove_val)
if (temp_list.length == 0){
master_list.push(remove_val)
}
else{
master_list = master_list.concat(temp_list);
}
}
//increment to move onto the next thing
index++
}
return master_list
}
function merge(left_dict, right_dict, on = [], how = 'inner'){
/*
This function will merge two dictionaries together
You provide a left dictionary, a right dictionary, a list of what key to join on and
what type of join you would like to do (right, left, inner)
a list of the merged dictionaries is returned
*/
//get the join type and initialize the master list of dictionaries that will be returned
var how_join = how.toLowerCase()
var master_list = []
//inner, right, and left joins are actually pretty similar in theory. The only major difference between
//left and right joins is the order that the data is processed. So the only difference is we call the
//merging function with the dictionaries in a different order
if (how_join === 'inner'){
master_list = dict_merge_loop_though(left_dict, right_dict, on, how_join)
}
else if (how_join === 'left'){
master_list = dict_merge_loop_though(left_dict, right_dict, on, how_join)
}
else if (how_join === 'right'){
master_list = dict_merge_loop_though(right_dict, left_dict, on, how_join)
}
else{
console.log('---- ERROR ----')
console.log('The "how" merge type is not correct. Please make sure it is either "inner", "left" or "right"')
console.log('---- ERROR ----')
}
return master_list
}
/*
-------------------- EXAMPLE --------------------
var arr1 = [
{'id': 1, 'test': 2, 'text':"hello", 'oid': 2},
{'id': 1, 'test': 1, 'text':"juhu", 'oid': 3},
{'id': 3, 'test': 3, 'text':"wohoo", 'oid': 4},
{'id': 4, 'test': 4, 'text':"yeehaw", 'oid': 1}
];
var arr2 = [
{'id': 1,'test': 2, 'name':"yoda"},
{'id': 1,'test': 1, 'name':"herbert"},
{'id': 3, 'name':"john"},
{'id': 4, 'name':"walter"},
{'id': 5, 'name':"clint"}
];
var test = merge(arr1, arr2, on = ['id', 'test'], how = 'left')
for (index in test){
dict_ = test[index]
console.log(dict_)
}
*/