拥有一个包含对象的数组,通过tenant_question_id
和tenant_option_id
查找对象,并且必须合并other1
和other2
(没有""
),并在数组中具有唯一的obj
输入
[
{
tenant_question_id: "3",
tenant_option_id: "22",
other1: "$20,000.00",
other2: ""
},
{
tenant_question_id: "3",
tenant_option_id: "22",
other1: "",
other2: "on"
},
{
tenant_question_id: "3",
tenant_option_id: "23",
other1: "",
other2: ""
},
{
tenant_question_id: "3",
tenant_option_id: "23",
other1: "$ 500.00",
other2: ""
}
]
预期结果
[
{
tenant_question_id: "3",
tenant_option_id: "22",
other1: "$20,000.00",
other2: "on"
},
{
tenant_question_id: "3",
tenant_option_id: "23",
other1: "$ 500.00",
other2: ""
}
]
尝试_.filter
,_.omit
找不到它。有什么想法吗?
答案 0 :(得分:0)
通过> x <- seq_len(ncol(cc))
> cc[, c(NA, x[-1])] == 1 & cc[, c(NA, head(x, -1))] == -1
[,1] [,2] [,3]
[1,] NA FALSE NA
[2,] NA TRUE FALSE
和tenant_question_id
的键创建索引,并在每次迭代中合并相关属性。然后只需获取索引的值即可。
tenant_option_id
答案 1 :(得分:0)
以下代码可以解决问题:
const mergedData = input.reduce((resultArray, tenantData) => {
const index = resultArray.findIndex(entry => entry.tenant_question_id === tenantData.tenant_question_id && entry.tenant_option_id === tenantData.tenant_option_id);
if (index!==-1) {
const existingData = resultArray[index];
if (!existingData.other1) {
existingData.other1 = tenantData.other1;
}
if (!existingData.other2) {
existingData.other2 = tenantData.other2;
}
} else {
resultArray.push(tenantData);
}
return resultArray;
}, []);
基本上遍历数组,然后逐渐填充结果数组。对于每个项目,检查是否已经存在具有tenant_question_id和tenant_option_id的项目,如果存在,则在现有对象上具有othery值(“”)的情况下,我们将覆盖other1和other2。如果不存在,则推送当前对象。
这确实存在以下问题:如果存在多个具有相同选项和键的对象,并且两个other2或两个other1都设置为非字符串值,则将使用迭代列表中的最新值。我假设您的数据集不包含此类条目。
答案 2 :(得分:0)
在crocks和ramda功能库的帮助下,您可以采用或多或少的声明式样式。
const { groupWith, eqProps, equals } = R
const { assign, map, reduce, compose } = crocks
const data = [
{tenant_question_id: "3", tenant_option_id: "22", other1: "$ 20,000.00", other2: ""},
{tenant_question_id: "3", tenant_option_id: "22", other1: "", other2: "on"},
{tenant_question_id: "3", tenant_option_id: "23", other1: "", other2: ""},
{tenant_question_id: "3", tenant_option_id: "23", other1: "$ 500.00", other2: ""}
];
const expected = [
{tenant_question_id: "3", tenant_option_id: "22", other1: "$ 20,000.00", other2: "on"},
{tenant_question_id: "3", tenant_option_id: "23", other1: "$ 500.00", other2: ""}
];
// This could be composed of entries, fromEntries, and filter,
// but this approach saves an iteration.
const stripFalsyValues = t =>
Object.entries(t)
.reduce((a, [k, v]) => ({...a, ...(v && {[k]: v})}), {})
const mergeAll = reduce(assign, {})
const isSameTenantOptionId = eqProps('tenant_option_id')
const groupByTenantOptionId = groupWith(isSameTenantOptionId)
const mergeTenants = compose(
map(mergeAll),
groupByTenantOptionId,
map(stripFalsyValues)
)
const result = mergeTenants(data)
console.log({expected, result})
<script src="https://unpkg.com/crocks/dist/crocks.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js" integrity="sha256-YN22NHB7zs5+LjcHWgk3zL0s+CRnzCQzDOFnndmUamY=" crossorigin="anonymous"></script>
请注意,关于第二个结果对象中缺少的other2: ""
,可以使用UI的默认属性在边缘进行处理。如果绝对必须传递空字符串,则可以将一些assignWhen = when(undefinedOption2, assign({option2: ""})
答案 3 :(得分:0)
我刚刚做了这个,它恰好返回您想要的输出。
var data = [{
tenant_question_id: "3",
tenant_option_id: "22",
other1: "$20,000.00",
other2: ""
},
{
tenant_question_id: "3",
tenant_option_id: "22",
other1: "",
other2: "on"
},
{
tenant_question_id: "3",
tenant_option_id: "23",
other1: "",
other2: ""
},
{
tenant_question_id: "3",
tenant_option_id: "23",
other1: "$ 500.00",
other2: ""
}
];
data = data.map(function(item, index, arr) {
// We remove the current mapped item from arr(self)
// So we can search within an arr that doesn't contain our "item" at the "index" position
arr.splice(index, 1);
if (item.other2 === '') {
var weFoundAnother = arr.find(function(elem, idx) {
return elem.tenant_question_id === item.tenant_question_id &&
elem.tenant_option_id === item.tenant_option_id &&
elem.other2.length;
});
if (weFoundAnother !== undefined) {
// We found our element and now we'll remove this too from "arr"
// Let's get "weFoundAnother" index first using
// -> arr.indexOf(weFoundAnother)
// Then we can remove it from "arr" because it is used now.
arr.splice(arr.indexOf(weFoundAnother), 1);
item.other2 = weFoundAnother.other2;
}
}
return item;
// Now we'll filter the empty slots ( items that we removed )
// And that's it
}).filter(function(i) {
return i !== undefined
})
console.clear();
console.log(data);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>