数组 - Javascript - 使用输入搜索过滤对象数组

Posted

技术标签:

【中文标题】数组 - Javascript - 使用输入搜索过滤对象数组【英文标题】:Arrays - Javascript - filter array of objects using input search 【发布时间】:2017-08-17 13:32:15 【问题描述】:

我正在尝试使用 react 过滤列表,但令人惊讶的是,对于这样一个常见的任务,在网上找不到任何东西来帮助我实现这一点。

我有一组用户,然后我想过滤它们(从名称开始 - 我可以按年龄进行过滤)。 该数组在我的 redux 存储中,如下所示。

let users = [
  
    name: 'Raul',
    age: 29
  ,
  
    name: 'Mario',
    age: 22
  
];

我的整个组件如下所示。

class Test extends Component 

    constructor(props) 
        super(props);

        this.state = 
            users: this.props.users

        ;

        this.filterList = this.filterList.bind(this);

    

    componentWillReceiveProps(nextProps) 

        this.setState(
            users: nextProps.users
        );

    

    filterList(event) 

        let users = this.state.users;
        users = users.filter(function(user)
        //unsure what to do here
        );
        this.setState(users: users);
    

  render()

    const userList = this.state.users.map((user) => 
      return <li>user.name user.age</li>;
    );

    return(
      <input type="text" placeholder="Search" onChange=this.filterList/>
      <ul>
         userList 
      </ul>
    );

  

【问题讨论】:

过滤条件是什么? 道歉@pablogq 按名称过滤。理想情况下两者都可以,但可以以名称开头 【参考方案1】:

如果您想过滤name,您可以使用.filter.startsWith.indexOf 一起为给定用户返回真或假。

您还在 onChange 事件上设置了一个新的用户列表,这迟早会导致一个空数组。这里我使用了仅由道具改变的user 状态,以及在击键发生时改变的filteredUsers

class Test extends React.Component 
  constructor(props) 
    super(props);

    this.state = 
      users: this.props.users,
      filteredUsers: this.props.users,
      q: ''
    ;

    this.filterList = this.filterList.bind(this);
    this.onChange = this.onChange.bind(this);
  

  componentWillReceiveProps(nextProps) 
    this.setState(
      
        users: nextProps.users,
        filteredUsers: nextProps.users
      ,
      () => this.filterList()
    );
  

  onChange(event) 
    const q = event.target.value.toLowerCase();
    this.setState( q , () => this.filterList());
  

  filterList() 
    let users = this.state.users;
    let q = this.state.q;

    users = users.filter(function(user) 
      return user.name.toLowerCase().indexOf(q) != -1; // returns true or false
    );
    this.setState( filteredUsers: users );
  

  render() 
    const userList = this.state.filteredUsers.map(user => 
      return <li>user.name user.age</li>;
    );

    return (
      <div>
        <input
          type="text"
          placeholder="Search"
          value=this.state.q
          onChange=this.onChange
        />
        <ul>
          userList
        </ul>
      </div>
    );
  


const userList = [
  
    name: 'Raul',
    age: 29
  ,
  
    name: 'Mario',
    age: 22
  
];

ReactDOM.render(<Test users=userList />, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>

【讨论】:

索引看起来如何? 你可以在那里做一个 if 语句。如果.indexOf(q) 的结果是-1,则返回false。否则,返回真。或user.name.toLowerCase().indexOf(q) != -1 一行完成。 谢谢!只有一个问题!用户数组不断增长,因此当添加更多用户时,它们不会显示。你知道我怎么能解决这个问题吗?! 更新了我的答案。当组件接收到新的 props 时,您还想更新 filteredUsers 状态。此外,您可能希望根据您想要的行为再次手动调用filterList 这是我已经尝试过的,但这会破坏过滤器搜索,因为当将新用户添加到数组时会再次显示整个数组。明白我的意思吗?【参考方案2】:

您还需要一个state 变量来存储搜索结果,用相同的数据初始化该变量,一旦用户键入任何内容,将过滤后的数据存储在其中,试试这个:

let users = [
  
    name: 'Raul',
    age: 29
  ,
  
    name: 'Mario',
    age: 22
  
];

class Test extends React.Component 

    constructor(props) 
        super(props);

        this.state = 
            users: users,
            result: users,
        ;

        this.filterList = this.filterList.bind(this);

    

    componentWillReceiveProps(nextProps) 

        this.setState(
            users: nextProps.users,            
        );

    

    filterList(event) 
        let value = event.target.value;
        let users = this.state.users, result=[];
        result = users.filter((user)=>
            return user.name.toLowerCase().search(value) != -1;
        );
        this.setState(result);
    

  render()

    const userList = this.state.result.map((user) => 
      return <li>user.name user.age</li>;
    );

    return(<div>
      <input type="text" placeholder="Search" onChange=this.filterList/>
      <ul>
        userList
      </ul>
      </div>
    );

  


ReactDOM.render(<Test/>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>


<div id='app'></div>

【讨论】:

【参考方案3】:
let datas =[
     
      "id":1,
      "title":"Ucat",
      "handle":"mi"
  ,
  
      "id":2,
      "title":"Acat",
      "handle":"csk"
  ,
  
      "id":3,
      "title":"Vcat",
      "handle":"kkr"
  ,
  
      "id":4,
      "title":"Atar",
      "handle":"pkbs"
  ];
const [search, setSearch] =useState(datas);
const handleInputChange = (e) => 
var dm = e.target.value;
var str =dm.toString();
var debug = datas.filter(x=> x["title"].toLowerCase().includes(str));
setSearch(debug);;


<input type="text"  onChange=handleInputChange/>
search.map((item)=>(
    <div key=item.id>
        <ul>
            <li>
            item.handle 
            <br/>
            item.title
            </li>
        </ul>
    </div>
));
  
  

【讨论】:

发布答案时请提供相关解释,以便提问者更好地理解解决方案【参考方案4】:

如果您想过滤列表,您必须有一个过滤条件。例如你有一个变量let filterAge = 18;

在这种情况下,您可以使用该值过滤用户列表

let users = users.filter(function(user)
    //return all users older or equal to filterAge
    return user.age >= filterAge;        
);

函数的每个结果等于 true,都将添加到 users 变量中。虚假的回报将把它排除在外。如何确定真/假取决于您。硬编码它(不是很有用),一个简单的等号语句(如上)或一个做高等数学的函数。你的选择。

【讨论】:

codepen.io/pjmtokyo/pen/ZGVjVV 这个似乎是根据具体情况进行的,没有像 if user is older than 18 那样明确的东西 你能看到search是在哪里定义的吗? 好吧,他在这里指定使用函数来确定(小写)名称是否具有给定的值(小写),使用搜索功能。 啊是啊,不知道有一个js search 方法。随时更新你的答案,我可以给你一个绿色的勾 他正在使用默认的javascript字符串搜索功能。有关详细信息,请参阅w3schools.com/jsref/jsref_search.asp。如果该字符串包含给定值,则返回字符串中该值开始的位置。如果它在开头,则该值返回 0。如果它不在其中,则返回 -1。但总的来说,他将搜索值与过滤器函数中的每个项目进行匹配。【参考方案5】:

这样对我来说总是很有效。

const [data, setData] = useState([name: 'Kondo', name: 'Gintoki'])

const handleFilterFilesTable = () => 
    return data
      .filter((element) => 
        if (searchText !== "") 
          return element?.name?.toLowerCase()?.includes(searchText?.toLowerCase())
        

        return element
      )
  

// ...
return (
 //...
 <Table data=handleFilterFilesTable() />
)

这样我就可以应用多个过滤器一起工作,只需像这样扩展 filter 方法

// ...
return data.filter().filter().filter()//...
// ...

【讨论】:

以上是关于数组 - Javascript - 使用输入搜索过滤对象数组的主要内容,如果未能解决你的问题,请参考以下文章

LeetCode35.搜索插入位置 JavaScript

如何在Java中处理一维数组的跳过输入

在javascript中搜索对象中的值[关闭]

JavaScript中数组元素的线性搜索

在 JavaScript 中通过 JSON 对象进行类似 Lucene 的搜索

[译]如何更好的使用javascript数组