[英]Filter JavaScript Array Based on Multiple Values
我正在尝试根据多个条件过滤 Javascript 字典。
我尝试执行以下步骤:
我创建了一个空字典变量
选择输入元素并获取原始 HTML 节点
将更改的元素的值保存为变量
将更改的元素的 id 保存为另一个变量
有条件地将值添加到过滤器 object
// 1. Create a variable to keep track of all the filters as an object. var filters = {}; // 3. Use this function to update the filters. function updateFilters() { // 4a. Save the element that was changed as a variable. let changedElement = d3.select(this); // 4b. Save the value that was changed as a variable. let elementValue = changedElement.property("value") console.log(elementValue); // 4c. Save the id of the filter that was changed as a variable. let filterId = changedElement.attr("id"); console.log(filterId); // 5. If a filter value was entered then add that filterId and value // to the filters list. Otherwise, clear that filter from the filters object. if (elementValue;= "") { filters[filterId] = elementValue; } else { delete filters[filterId]. } // 6; Call function to apply all filters and rebuild the table filterTable();
// 7. Use this function to filter the table when data is entered.
function filterTable() {
// 8. Set the filtered data to the tableData.
let filteredData = tableData;
// 9. Loop through all of the filters and keep any data that
// matches the filter values
Object.entries(filters).forEach(([filterId, elementValue]) => {
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.datetime === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.city === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.state === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.country === elementValue);
}
if (filters[filterId] != "") {
filteredData = filteredData.filter(entry => entry.shape === elementValue);
}
};
// 10. Finally, rebuild the table using the filtered data
buildTable(filteredData);
}
// 2. Attach an event to listen for changes to each filter
d3.selectAll("input").on("change", updateFilters);
// Build the table when the page loads
buildTable(tableData);
界面如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<!-- <meta http-equiv="X-UA-Compatible" content="IE=edge"> -->
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.7/superhero/bootstrap.min.css"> -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css">
<script type="text/javascript" charset="utf8" src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<title>UFO Finder</title>
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm"
crossorigin="anonymous"
/>
<link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet">
<link rel="stylesheet" href="static/css/style.css">
</head>
<body class="bg-dark">
<div class="wrapper">
<nav class="navbar navbar-dark bg-dark navbar-expand-lg">
<a class="navbar-brand" href="index.html">UFO Sightings</a>
</nav>
<div class="jumbotron">
<h1 class="display-4">The Truth Is Out There</h1>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-4">
<h3>UFO Sightings: Fact or Fancy? <small>Ufologists Weigh In</small></h3>
</div>
<div class="col-md-8">
<p>Some Text</p>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-3">
<form class="bg-dark">
<p>Filter Search</p>
<ul class="list-group bg-dark">
<li class="list-group-item bg-dark">
<label for="date">Enter Date</label>
<input type="text" placeholder="1/10/2010" id="datetime"/>
</li>
<li class="list-group-item bg-dark">
<label for="city">Enter a City</label>
<input type="text" placeholder="roswell" id="city">
</li>
<li class="list-group-item bg-dark">
<label for="state">Enter a State</label>
<input type="text" placeholder="ca" id="state">
</li>
<li class="list-group-item bg-dark">
<label for="Country">Enter a Country</label>
<input type="text" placeholder="us" id="country">
</li>
<li class="list-group-item bg-dark">
<label for="Shape">Enter a Shape</label>
<input type="text" placeholder="crcle" id="shape">
</li>
<!-- <li class="list-group-item bg-dark">
<button id="filter-btn" type="button" class="btn btn-dark" >Clear Table</button>
</li> -->
</ul>
</form>
</div>
<div class="col-md-9">
<table class="table table-striped">
<thead>
<tbody>
<tr>
<th>Date</th>
<th>City</th>
<th>State</th>
<th>Country</th>
<th>Shape</th>
<th>Duration</th>
<th>Comments</th>
</tr>
</tbody>
</thead>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.11.0/d3.js"></script>
<script type="text/javascript" src="./static/js/data.js"></script>
<script type="text/javascript" src="./static/js/ufo_starterCode.js"></script>
</body>
</html>
var data = [
{
datetime: "1/1/2010",
city: "benton",
state: "ar",
country: "us",
shape: "circle",
durationMinutes: "5 mins.",
comments: "4 bright green circles high in the sky going in circles then one bright green light at my front door."
},
{
datetime: "1/1/2010",
city: "bonita",
state: "ca",
country: "us",
shape: "light",
durationMinutes: "13 minutes",
comments: "Three bright red lights witnessed floating stationary over San Diego New Years Day 2010"
}
];
目标是能够根据用户输入的过滤搜索条件过滤表中的记录。 请注意,我对 Javascript 很陌生。 任何帮助表示赞赏。
由于您是 JavaScript 的新手,我建议您从基础开始。 这意味着:尽量不使用库和框架。 在下面的代码片段中,我删除了您对引导程序、D3、数据表和 jQuery 的引用,因为它们对于解决过滤表的基本问题并不是真正需要的。 这也是在 SO 中发布代码的要求。 您应该始终尝试提供“MCVE”(最低限度完整且可行的示例)。
我为过滤选择了一个非常基本的概念:看到输入字段直接对应于表的前五列,我应用了遍历所有这些输入的值并将它们与相应的表值进行比较的技巧。 这些值是通过在表行( <tr>
)上执行forEach()
循环找到的,然后确保我得到前五个<td>
的“正匹配”( [...tr.children].slice(0,5)
) 的每一行。 文本比较是在每个inp.value
的小写版本(存储在vals[I]
中)和相应的td.textContent
的,但前提是vals[i]
不为空(否则返回正匹配,作为空的vals[i]
意味着没有对该列进行过滤)。 因此,如果所有五列( .every()
-loop)都满足“匹配”条件,则当前<tr>
的.style.display
属性设置为""
,否则设置为"none"
。
const data = [ { datetime: "1/1/2010", city: "benton", state: "ar", country: "us", shape: "circle", durationMinutes: "5 mins.", comments: "4 bright green circles high in the sky going in circles then one bright green light at my front door." }, { datetime: "1/1/2010", city: "bonita", state: "ca", country: "us", shape: "light", durationMinutes: "13 minutes", comments: "Three bright red lights witnessed floating stationary over San Diego New Years Day 2010" }, { datetime: "1/13/2010", city: "Bonita", state: "ca", country: "us", shape: "square", durationMinutes: "3 minutes", comments: "Early in January we saw a blue square appear right out of nowhere." }]; // fill table: const tb=document.querySelector("table tbody"); tb.innerHTML= data.map(r=>"<tr><td>"+Object.values(r).join("</td><td>")+"</td></td>").join("\n"); // filter table: const inps=[...document.querySelectorAll("ul input")]; document.querySelector("ul").addEventListener("input",ev=>{ const vals=inps.map(inp=>inp.value.toLowerCase()); // filter table according to content of first 5 columns: [...tb.children].forEach(tr=> // check for every table record: tr.style.display=[...tr.children].slice(0,5).every((td,i)=> vals[i]==="" || td.textContent.toLowerCase().includes(vals[i]) )? "": "none" // show record if vals[i]==="" or if vals[i] is part of the corresponding column contents ) })
.table-striped tbody tr:nth-child(odd) {background-color:#ddd}
<div class="wrapper"> <div class="jumbotron"> <h1 class="display-4">The Truth Is Out There</h1> </div> <div class="container-fluid"> <div class="row"> <div class="container-fluid"> <div class="row"> <div class="col-md-3"> <form class="bg-dark"> <p>Filter Search</p> <ul class="list-group bg-dark"> <li class="list-group-item bg-dark"> <label for="date">Enter Date</label> <input type="text" placeholder="1/10/2010" id="datetime" /> </li> <li class="list-group-item bg-dark"> <label for="city">Enter a City</label> <input type="text" placeholder="roswell" id="city"> </li> <li class="list-group-item bg-dark"> <label for="state">Enter a State</label> <input type="text" placeholder="ca" id="state"> </li> <li class="list-group-item bg-dark"> <label for="Country">Enter a Country</label> <input type="text" placeholder="us" id="country"> </li> <li class="list-group-item bg-dark"> <label for="Shape">Enter a Shape</label> <input type="text" placeholder="crcle" id="shape"> </li> <li class="list-group-item bg-dark"> <button id="filter-btn" type="button" class="btn btn-dark">Clear Table</button> </li> </ul> </form> </div> <div class="col-md-9"> <table class="table table-striped"> <thead> <tr> <th>Date</th> <th>City</th> <th>State</th> <th>Country</th> <th>Shape</th> <th>Duration</th> <th>Comments</th> </tr> </thead> <tbody></tbody> </table> </div> </div> </div> </div> </div> </div>
原始代码试图在循环通过过滤器时过滤数据 object; 下面的代码实现循环通过过滤器 object,同时循环通过数据 object。
由于我的行数总是多于过滤器,因此我运行了一次 .filter 方法,而不是像我最初尝试的那样运行每个过滤器。
// 9. Loop through all of the filters and keep any data that matches the filter values
let filteredData = tableData.filter((obj) => {
for(filterId in filters) {
if(obj[filterId] !== filters[filterId]) {
return false;
}
}
return true;
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.