筛选具有多个AND组合属性对的对象数组



我的javascript数组

const response = [
{
"userId": "1",
"questionId": "1",
"answeredIndex": 1
},
{
"userId": "1",
"questionId": "2",
"answeredIndex": 0
},
{
"userId": "2",
"questionId": "1",
"answeredIndex": 1
},
{
"userId": "2",
"questionId": "2",
"answeredIndex": 0
},
{
"userId": "3",
"questionId": "1",
"answeredIndex": 0
},
{
"userId": "3",
"questionId": "2",
"answeredIndex": 3
},
{
"userId": "4",
"questionId": "1",
"answeredIndex": 1
},
{
"userId": "4",
"questionId": "2",
"answeredIndex": 0
},
{
"userId": "5",
"questionId": "1",
"answeredIndex": 0
},
{
"userId": "5",
"questionId": "2",
"answeredIndex": 0
}]

我正在寻找一个将返回userId数组的解决方案。每个用户回答了两个问题(questionId:1和questionId:2(。我希望回答这两个问题的用户都是一样的。所以,我想用AND条件过滤我的数组,如下所示:

如果用户为questionId:1选择了answeredIndex:1,并且如果同一用户也为questionId:2选择了ansoweredIndex:0,那么,我希望将此用户推送到结果数组中。

我尝试了下面的代码,但不幸的是它不起作用。

const targetUsers: string[] = [];
response.forEach((feedback) => {
if ((feedback.questionId === '1' && feedback.answeredIndex === 1) ||
feedback.questionId === '2' && feedback.answeredIndex === 0) {
targetUsers.push(feedback.userId);
}
});
console.log([...new Set(targetUsers)]);

我的预期输出应该如下:

[
{
"userId": "1",
"questionId": "1",
"answeredIndex": 1
},
{
"userId": "1",
"questionId": "2",
"answeredIndex": 0
},
{
"userId": "2",
"questionId": "1",
"answeredIndex": 1
},
{
"userId": "2",
"questionId": "2",
"answeredIndex": 0
},
{
"userId": "4",
"questionId": "1",
"answeredIndex": 1
},
{
"userId": "4",
"questionId": "2",
"answeredIndex": 0
}]

因此,对于每个用户,属性对(questionId,answeredIndex(的组合应该是(1,1(AND(2,0(,只有这样才会考虑该用户。如果有人在这里帮助我,我将不胜感激。提前谢谢。

对于所有用户的答案,可以采用单循环方法。然后只选那些答对了问题的人。

这种方法计算正确答案,然后根据需要的计数进行筛选。

const
response = [{ userId: "1", questionId: "1", answeredIndex: 1 }, { userId: "1", questionId: "2", answeredIndex: 0 }, { userId: "2", questionId: "1", answeredIndex: 1 }, { userId: "2", questionId: "2", answeredIndex: 0 }, { userId: "3", questionId: "1", answeredIndex: 0 }, { userId: "3", questionId: "2", answeredIndex: 3 }, { userId: "4", questionId: "1", answeredIndex: 1 }, { userId: "4", questionId: "2", answeredIndex: 0 }, { userId: "5", questionId: "1", answeredIndex: 0 }, { userId: "5", questionId: "2", answeredIndex: 0 }],
answers = { 1: 1, 2: 0 },
temp = response.reduce((r, { userId, questionId, answeredIndex }) => {
r[userId] ??= 0;
r[userId] += answers[questionId] === answeredIndex;
return r;
}, {}),
targetUsers = Object
.keys(temp)
.filter((count => k => temp[k] === count)(Object.keys(answers).length));

console.log(targetUsers);

这是一个技巧,因为过滤器依赖于数组中的多个项。更容易理解的解决方法是保留我们已经迭代过的先前答案的信息:

const response = [
{
"userId": "1",
"questionId": "1",
"answeredIndex": 1
},
{
"userId": "1",
"questionId": "2",
"answeredIndex": 0
},
{
"userId": "2",
"questionId": "1",
"answeredIndex": 1
},
{
"userId": "2",
"questionId": "2",
"answeredIndex": 0
},
{
"userId": "3",
"questionId": "1",
"answeredIndex": 0
},
{
"userId": "3",
"questionId": "2",
"answeredIndex": 3
},
{
"userId": "4",
"questionId": "1",
"answeredIndex": 1
},
{
"userId": "4",
"questionId": "2",
"answeredIndex": 0
},
{
"userId": "5",
"questionId": "1",
"answeredIndex": 0
},
{
"userId": "5",
"questionId": "2",
"answeredIndex": 0
}]

//object to make it easier to add mulitple questions
const rightQuestions = {
"1": 1,
"2": 0
}
//create a map to use as reference for each user
const usersToKeep = new Map()
response.forEach(item => {

//if it's false, it has already an wrong answer
if(usersToKeep.get(item.userId) === false) {
return
}

// from here it either has not responded yet (undefined), or has a right answer (true)

if(item.answeredIndex === rightQuestions[item.questionId]) {
//the answer is valid
usersToKeep.set(item.userId, true)
} else {
//the answer is not valid
usersToKeep.set(item.userId, false)
}
})
//now filter for the users we should keep
const results = response.filter(item => usersToKeep.get(item.userId))
//clear the map (not needed if the filter is inside a funcion)
usersToKeep.clear()

不确定这是否是一个愚蠢的想法,但它可能允许使用复杂的过滤器:

const responses = [
{ "userId": "1", "questionId": "1", "answeredIndex": 1 },
{ "userId": "1", "questionId": "2", "answeredIndex": 0 },
{ "userId": "2", "questionId": "1", "answeredIndex": 1 },
{ "userId": "2", "questionId": "2", "answeredIndex": 0 },
{ "userId": "3", "questionId": "1", "answeredIndex": 0 },
{ "userId": "3", "questionId": "2", "answeredIndex": 3 },
{ "userId": "4", "questionId": "1", "answeredIndex": 1 },
{ "userId": "4", "questionId": "2", "answeredIndex": 0 },
{ "userId": "5", "questionId": "1", "answeredIndex": 0 },
{ "userId": "5", "questionId": "2", "answeredIndex": 0 }
];
// intersection from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set
function intersection(setA, setB) {
let _intersection = new Set()
for (let elem of setB) {
if (setA.has(elem)) {
_intersection.add(elem)
}
}
return _intersection
}
const matchers = [
(item) => item.questionId === '1' && item.answeredIndex === 1,
(item) => item.questionId === '2' && item.answeredIndex === 0,
];
const matching_users = matchers.map(
(matcher) =>
responses.reduce(
(acc, response) => matcher(response) ? acc.add(response.userId) : acc,
new Set()
)
).reduce(
(acc, set) => intersection(acc, set)
);
const result = responses.filter((item) => matching_users.has(item.userId));
console.log(result);

解释它(希望(的作用:

对于每个匹配器,它会检查每个响应,看看它是否符合条件,如果符合,它会将其添加到包含用户id的集合中。然后,它找到用户id集合的公共元素,以找到匹配所有匹配器的用户id。最后,它根据用户id列表过滤响应。

最新更新