React 中具有多个值的多个列表框搜索数组过滤器
Multiple listboxes with multiple values search array filter in React
我正在从 O365 REST 调用中填充一个对象,然后使用 SPfx FluentUI Detailslist 应用程序中的多select 下拉菜单进行过滤。我的代码是附加来自每个下拉列表的任何值的结果,而不是缩小结果以满足所有过滤条件。
代码笔示例:https://codepen.io/detailcode/pen/VwmdZoo
<!DOCTYPE html><html><body>
<select id="lstTitle" multiple size="4">
<option value="" selected>(Select Multi Values)</option>
<option value="Apple">Apple</option>
<option value="Pear">Pear</option>
<option value="Grape">Grape</option>
<option value="Banana">Banana</option>
<option value="Beet">Beet</option>
<option value="Grapefruit">Grapefruit</option>
<option value="Lemon">Lemon</option>
</select>
<select id="lstColor" multiple size="4">
<option value="" selected>(Select Multi Values)</option>
<option value="Red">Red</option>
<option value="Green">Green</option>
<option value="Yellow">Yellow</option>
</select>
<select id="lstTaste" multiple size="4">
<option value="" selected>(Select Multi Values)</option>
<option value="Sweet">Sweet</option>
<option value="Sour">Sour</option>
<option value="Bitter">Bitter</option>
</select>
<input id="butFilter" type="button" value="Filter" onclick="butFilter_Click()" />
<p>All Results:</p>
<div id="cssResults1" style="padding:3px 10px;border:1px solid #000;">No data</div>
<p>Single Select Result:</p>
<div id="cssResults2" style="padding:3px 10px;border:1px solid #000;">No data</div>
<p>Multi Select Result: (Selecting Apple, Pear, Grape, Red, Green, Sweet, Sour) <strong>Desired result being records 1, 2, 4, 5, 6</strong></p>
<div id="cssResults3" style="padding:3px 10px;border:1px solid #000;">No data</div>
<script>
let data = [
{ 'id': 1, 'title': 'Apple', 'color': 'Red', 'taste': 'Sweet', },
{ 'id': 2, 'title': 'Apple', 'color': 'Green', 'taste': 'Sour', },
{ 'id': 3, 'title': 'Apple', 'color': 'Yellow', 'taste': 'Sweet', },
{ 'id': 4, 'title': 'Pear', 'color': 'Green', 'taste': 'Sweet', },
{ 'id': 5, 'title': 'Grape', 'color': 'Red', 'taste': 'Sweet', },
{ 'id': 6, 'title': 'Grape', 'color': 'Green', 'taste': 'Sour', },
{ 'id': 7, 'title': 'Banana', 'color': 'Yellow', 'taste': 'Sweet', },
{ 'id': 8, 'title': 'Beet', 'color': 'Red', 'taste': 'Bitter', },
{ 'id': 9, 'title': 'Grapefruit', 'color': 'Yellow', 'taste': 'Bitter', },
{ 'id': 10, 'title': 'Lemon', 'color': 'Yellow', 'taste': 'Sour', },
]
//var result1 = data.filter(e => e.color == 'Yellow' && e.taste == 'Sweet');
console.log(data);
document.getElementById("cssResults1").innerHTML = "<p>" + JSON.stringify(data) + "<p>";
function butFilter_Click() {
var result2 = data.filter(e =>
e.title == (document.getElementById("lstTitle").value != "" ? document.getElementById("lstTitle").value : e.title) &&
e.color == (document.getElementById("lstColor").value != "" ? document.getElementById("lstColor").value : e.color) &&
e.taste == (document.getElementById("lstTaste").value != "" ? document.getElementById("lstTaste").value : e.taste));
document.getElementById("cssResults2").innerHTML = "<p>" + JSON.stringify(result2) + "<p>";
console.log(result2); // LOG SINGLE SELECT RESULT
const valTitle = Array.apply(null, document.getElementById("lstTitle").options).filter(option => option.selected).map(option => option.value);
const valColor = Array.apply(null, document.getElementById("lstColor").options).filter(option => option.selected).map(option => option.value);
const valTaste = Array.apply(null, document.getElementById("lstTaste").options).filter(option => option.selected).map(option => option.value);
console.log(valTitle); // LOG lstTitle MULTI VALUES
console.log(valColor); // LOG lstColor MULTI VALUES
console.log(valTaste); // LOG lstTaste MULTI VALUES
// INCLUSIVELY ADDS TO RESULT VERSUS MATCHING ALL KEY VALUES
let tempContat = [];
let temp;
for(var i = 0; i < valTitle.length; i++) {
temp = data.filter(e => e.title == (valTitle[i] != "" ? valTitle[i] : e.title))
tempContat = tempContat.concat(temp);
}
for(var i = 0; i < valColor.length; i++) {
temp = data.filter(e => e.color == (valColor[i] != "" ? valColor[i] : e.color))
tempContat = tempContat.concat(temp);
}
for(var i = 0; i < valTaste.length; i++) {
temp = data.filter(e => e.taste == (valTaste[i] != "" ? valTaste[i] : e.taste))
tempContat = tempContat.concat(temp);
}
var result3 = tempContat;
document.getElementById("cssResults3").innerHTML = "<p>" + JSON.stringify(result3) + "<p>";
console.log(result3); // LOG MULTI SELECT RESULT
}
</script>
</body></html>
已更新:如何过滤一个对象使其包含在最终结果中(与 results3 相反)?当 select 对水果(Apple、Pear、Grape)、颜色(Red、Green)和口味(Sweet、Sour)进行测试时,预期结果应为 ID 1、2、4、5 和 6 .如果每个搜索条件都不符合,应该像在搜索引擎过滤器中一样排除。
问题是您拥有的每个 for 循环都独立于用于过滤对象的谓词。要解决此问题,您需要将谓词全部置于同一范围内,以便由于当前谓词的范围而不会添加应省略的内容。例如:
for(var i = 0; i < valTitle.length; i++) {
// this predicate will remove all things relating to titles
temp = data.filter(e => e.title == (valTitle[i] != "" ? valTitle[i] : e.title))
tempContat = tempContat.concat(temp);
}
// these for loops are independent and all re-use the same 'data' so its possible for the previous loop's omitted objects to be filtered in again
// because the filter constraint in the next for loop doesn't include the previous ones constraints
for(var i = 0; i < valColor.length; i++) {
// this filter's predicate is unaware that 'e.title' of some type should be omitted, it only knows to filter out colors of some type `valColor[i]`
temp = data.filter(e => e.color == (valColor[i] != "" ? valColor[i] : e.color))
// here some titles that should be omitted are added in because it matched on the color from the predicate above
tempContat = tempContat.concat(temp);
}
for(var i = 0; i < valTaste.length; i++) {
temp = data.filter(e => e.taste == (valTaste[i] != "" ? valTaste[i] : e.taste))
tempContat = tempContat.concat(temp);
}
因此也可以添加重复项,因为过滤器基于 data
,它永远不会改变,并且是要过滤的所有可用内容。
要解决这个问题,您需要组合谓词,下面我通过使用 1 个过滤器并将谓词放在一起来做到这一点。
const result3 = data.filter((e) => {
// element must have at least one of these titles to be filtered in
if (!valTitle.some((title) => e.title == (title != "" ? title : e.title))) {
return false;
}
// and
// element must have at least one of these colors to be filtered in
if (!valColor.some((color) => e.color == (color != "" ? color : e.color))) {
return false;
}
// and
// element must have at least one of these tastes to be filtered in
if (!valTaste.some((taste) => e.taste == (taste != "" ? taste : e.taste))) {
return false;
}
return true;
});
您可以执行与上述解决方案类似的操作。
我正在从 O365 REST 调用中填充一个对象,然后使用 SPfx FluentUI Detailslist 应用程序中的多select 下拉菜单进行过滤。我的代码是附加来自每个下拉列表的任何值的结果,而不是缩小结果以满足所有过滤条件。
代码笔示例:https://codepen.io/detailcode/pen/VwmdZoo
<!DOCTYPE html><html><body>
<select id="lstTitle" multiple size="4">
<option value="" selected>(Select Multi Values)</option>
<option value="Apple">Apple</option>
<option value="Pear">Pear</option>
<option value="Grape">Grape</option>
<option value="Banana">Banana</option>
<option value="Beet">Beet</option>
<option value="Grapefruit">Grapefruit</option>
<option value="Lemon">Lemon</option>
</select>
<select id="lstColor" multiple size="4">
<option value="" selected>(Select Multi Values)</option>
<option value="Red">Red</option>
<option value="Green">Green</option>
<option value="Yellow">Yellow</option>
</select>
<select id="lstTaste" multiple size="4">
<option value="" selected>(Select Multi Values)</option>
<option value="Sweet">Sweet</option>
<option value="Sour">Sour</option>
<option value="Bitter">Bitter</option>
</select>
<input id="butFilter" type="button" value="Filter" onclick="butFilter_Click()" />
<p>All Results:</p>
<div id="cssResults1" style="padding:3px 10px;border:1px solid #000;">No data</div>
<p>Single Select Result:</p>
<div id="cssResults2" style="padding:3px 10px;border:1px solid #000;">No data</div>
<p>Multi Select Result: (Selecting Apple, Pear, Grape, Red, Green, Sweet, Sour) <strong>Desired result being records 1, 2, 4, 5, 6</strong></p>
<div id="cssResults3" style="padding:3px 10px;border:1px solid #000;">No data</div>
<script>
let data = [
{ 'id': 1, 'title': 'Apple', 'color': 'Red', 'taste': 'Sweet', },
{ 'id': 2, 'title': 'Apple', 'color': 'Green', 'taste': 'Sour', },
{ 'id': 3, 'title': 'Apple', 'color': 'Yellow', 'taste': 'Sweet', },
{ 'id': 4, 'title': 'Pear', 'color': 'Green', 'taste': 'Sweet', },
{ 'id': 5, 'title': 'Grape', 'color': 'Red', 'taste': 'Sweet', },
{ 'id': 6, 'title': 'Grape', 'color': 'Green', 'taste': 'Sour', },
{ 'id': 7, 'title': 'Banana', 'color': 'Yellow', 'taste': 'Sweet', },
{ 'id': 8, 'title': 'Beet', 'color': 'Red', 'taste': 'Bitter', },
{ 'id': 9, 'title': 'Grapefruit', 'color': 'Yellow', 'taste': 'Bitter', },
{ 'id': 10, 'title': 'Lemon', 'color': 'Yellow', 'taste': 'Sour', },
]
//var result1 = data.filter(e => e.color == 'Yellow' && e.taste == 'Sweet');
console.log(data);
document.getElementById("cssResults1").innerHTML = "<p>" + JSON.stringify(data) + "<p>";
function butFilter_Click() {
var result2 = data.filter(e =>
e.title == (document.getElementById("lstTitle").value != "" ? document.getElementById("lstTitle").value : e.title) &&
e.color == (document.getElementById("lstColor").value != "" ? document.getElementById("lstColor").value : e.color) &&
e.taste == (document.getElementById("lstTaste").value != "" ? document.getElementById("lstTaste").value : e.taste));
document.getElementById("cssResults2").innerHTML = "<p>" + JSON.stringify(result2) + "<p>";
console.log(result2); // LOG SINGLE SELECT RESULT
const valTitle = Array.apply(null, document.getElementById("lstTitle").options).filter(option => option.selected).map(option => option.value);
const valColor = Array.apply(null, document.getElementById("lstColor").options).filter(option => option.selected).map(option => option.value);
const valTaste = Array.apply(null, document.getElementById("lstTaste").options).filter(option => option.selected).map(option => option.value);
console.log(valTitle); // LOG lstTitle MULTI VALUES
console.log(valColor); // LOG lstColor MULTI VALUES
console.log(valTaste); // LOG lstTaste MULTI VALUES
// INCLUSIVELY ADDS TO RESULT VERSUS MATCHING ALL KEY VALUES
let tempContat = [];
let temp;
for(var i = 0; i < valTitle.length; i++) {
temp = data.filter(e => e.title == (valTitle[i] != "" ? valTitle[i] : e.title))
tempContat = tempContat.concat(temp);
}
for(var i = 0; i < valColor.length; i++) {
temp = data.filter(e => e.color == (valColor[i] != "" ? valColor[i] : e.color))
tempContat = tempContat.concat(temp);
}
for(var i = 0; i < valTaste.length; i++) {
temp = data.filter(e => e.taste == (valTaste[i] != "" ? valTaste[i] : e.taste))
tempContat = tempContat.concat(temp);
}
var result3 = tempContat;
document.getElementById("cssResults3").innerHTML = "<p>" + JSON.stringify(result3) + "<p>";
console.log(result3); // LOG MULTI SELECT RESULT
}
</script>
</body></html>
已更新:如何过滤一个对象使其包含在最终结果中(与 results3 相反)?当 select 对水果(Apple、Pear、Grape)、颜色(Red、Green)和口味(Sweet、Sour)进行测试时,预期结果应为 ID 1、2、4、5 和 6 .如果每个搜索条件都不符合,应该像在搜索引擎过滤器中一样排除。
问题是您拥有的每个 for 循环都独立于用于过滤对象的谓词。要解决此问题,您需要将谓词全部置于同一范围内,以便由于当前谓词的范围而不会添加应省略的内容。例如:
for(var i = 0; i < valTitle.length; i++) {
// this predicate will remove all things relating to titles
temp = data.filter(e => e.title == (valTitle[i] != "" ? valTitle[i] : e.title))
tempContat = tempContat.concat(temp);
}
// these for loops are independent and all re-use the same 'data' so its possible for the previous loop's omitted objects to be filtered in again
// because the filter constraint in the next for loop doesn't include the previous ones constraints
for(var i = 0; i < valColor.length; i++) {
// this filter's predicate is unaware that 'e.title' of some type should be omitted, it only knows to filter out colors of some type `valColor[i]`
temp = data.filter(e => e.color == (valColor[i] != "" ? valColor[i] : e.color))
// here some titles that should be omitted are added in because it matched on the color from the predicate above
tempContat = tempContat.concat(temp);
}
for(var i = 0; i < valTaste.length; i++) {
temp = data.filter(e => e.taste == (valTaste[i] != "" ? valTaste[i] : e.taste))
tempContat = tempContat.concat(temp);
}
因此也可以添加重复项,因为过滤器基于 data
,它永远不会改变,并且是要过滤的所有可用内容。
要解决这个问题,您需要组合谓词,下面我通过使用 1 个过滤器并将谓词放在一起来做到这一点。
const result3 = data.filter((e) => {
// element must have at least one of these titles to be filtered in
if (!valTitle.some((title) => e.title == (title != "" ? title : e.title))) {
return false;
}
// and
// element must have at least one of these colors to be filtered in
if (!valColor.some((color) => e.color == (color != "" ? color : e.color))) {
return false;
}
// and
// element must have at least one of these tastes to be filtered in
if (!valTaste.some((taste) => e.taste == (taste != "" ? taste : e.taste))) {
return false;
}
return true;
});
您可以执行与上述解决方案类似的操作。