gpt4 book ai didi

javascript - 在对象数组中,返回任何值与特定字符串匹配的对象

转载 作者:搜寻专家 更新时间:2023-10-30 22:42:42 24 4
gpt4 key购买 nike

我正在我的应用程序中实现搜索功能。 UI 中的搜索结果基于对象数组返回。本质上,我要做的是遍历每个对象中的名称、custNumber 和潜行值,并且只返回包含字符串(从用户搜索栏生成)的值的对象。这个想法是用户可以搜索对象中的任何内容并产生正确的结果

这是我的数组

var result = [{
name: 'Donna Shomaker',
custNumber: '6658924351',
sneak: 'string1 string1 string1',
foo: false,
bar: false,
},
{
name: 'Ron Duluth',
custNumber: '8812654434',
sneak: 'string2 string2 string2',
foo: false,
bar: false,
},
{
name: 'Jimmy Dawson',
custNumber: '8908198230',
sneak: 'string3 string3 string3',
foo: false,
bar: false,
}
]

这就是我得到的结果

return result.filter(convo => {
return convo.name.toLowerCase().includes(searchbarVal.toLowerCase())
})

这里明显的问题是,这只是返回基于名称值的对象。但是,我需要它将每个对象中的名称、custNumber 和潜行值与用户搜索进行比较。我已经尝试了 forEach、object.values 和 object.entries 方法,但无法让它们工作。非常感谢这里的任何帮助!!

最佳答案

递归搜索

这是我写的关于 recently 的主题。这是一个通用的 deepFind。它以递归方式工作,可以“搜索”任何输入值。

下面我们构造一组简单的数据,然后展示deepFind如何搜索数据并返回匹配项

const data =
[ { a: 1, b: 1 }
, { a: 2, b: 2, c: { d: [ { e: 2 } ] } }
, { a: 3, b: { c: { d: { e: { f: 3 } } } } }
]

const deepFind = (f, obj = {}) =>
{ if (Object (obj) === obj)
{ if (f (obj) === true)
return obj

for (const [ k, v ] of Object.entries (obj))
{ const res =
deepFind (f, v)

if (res !== undefined)
return res
}
}

return undefined
}

console.log
( deepFind (x => x.a === 1, data) // { a: 1, b: 1 }
, deepFind (x => x.e === 2, data) // { e: 2 }
, deepFind (x => Array.isArray(x.d), data) // { d: [ { e: 2 } ] }
, deepFind (x => x.f === 3, data) // { f: 3 }
, deepFind (x => x.e && x.e.f === 3, data) // { e: { f: 3 } }
, deepFind (x => x.z === 9, data) // undefined
)

以上deepFind 只能通过直接使用=== 匹配值来工作。但是,因为它接受高阶函数 f,所以我们可以以有意义的方式专门化它的行为。

使用 deepFind 进行字符串匹配

下面我们使用 deepFind 对通用字符串匹配 search 函数进行编码>

const search = (query = "", data) =>
deepFind
( o =>
Object.values (o) .some (v =>
String (v) === v && v .includes (query))
, data
)

search ("D", result)
// { name: "Donna Shomaker", ... }

search ("Du", result)
// { name: "Ron Duluth", ... }

search ("ng3", result)
// { name: "Jimmy Dawson", sneak: "string3 string3 string3", ... }

search ("zzz", result)
// undefined

在自己的浏览器中验证结果

const deepFind = (f, obj = {}) =>
{ if (Object (obj) === obj)
{ if (f (obj) === true)
return obj

for (const [ k, v ] of Object.entries (obj))
{ const res =
deepFind (f, v)

if (res !== undefined)
return res
}
}

return undefined
}

const search = (query = "", data) =>
deepFind
( o =>
Object.values (o) .some (v =>
String (v) === v && v .includes (query))
, data
)

const result =
[ { name: 'Donna Shomaker'
, custNumber: '6658924351'
, sneak: 'string1 string1 string1'
, foo: false
, bar: false
}
, { name: 'Ron Duluth'
, custNumber: '8812654434'
, sneak: 'string2 string2 string2'
, foo: false
, bar: false
}
, { name: 'Jimmy Dawson'
, custNumber: '8908198230'
, sneak: 'string3 string3 string3'
, foo: false
, bar: false
}
]

console.log (search ("D", result))
// { name: "Donna Shomaker", ... }

console.log (search ("Du", result))
// { name: "Ron Duluth", ... }

console.log (search ("ng3", result))
// { name: "Jimmy Dawson", sneak: "string3 string3 string3", ... }

console.log (search ("zzz", result))
// undefined

返回多个搜索结果

上面的程序只返回第一个 匹配项。如果您想返回所有结果,我们可以使用非常适合此任务的生成器来实现

const deepFindAll = function* (f, o = {})
{ if (Object (o) === o)
{ if (f (o) === true)
yield o
for (const [ _, v ] of Object.entries (o))
yield* deepFindAll (f, v)
}
}

现在我们使用我们的新生成器实现searchAll

const searchAll = (query = "", data = {}) =>
Array.from
( deepFindAll
( o =>
Object.values (o) .some (v =>
String (v) === v && v .includes (query))
, data
)
)

searchAll ("81", result)
// [ { custNumber: '8812654434', ... }
// , { custNumber: '8908198230', ... }
// ]

searchAll ("Du", result)
// [ { name: "Ron Duluth", ... } ]

searchAll ("zzz", result)
// []

在下面的浏览器中运行searchAll

const deepFindAll = function* (f, o = {})
{ if (Object (o) === o)
{ if (f (o) === true)
yield o
for (const [ _, v ] of Object.entries (o))
yield* deepFindAll (f, v)
}
}

const searchAll = (query = "", data = {}) =>
Array.from
( deepFindAll
( o =>
Object.values (o) .some (v =>
String (v) === v && v .includes (query))
, data
)
)

const result =
[ { name: 'Donna Shomaker'
, custNumber: '6658924351'
, sneak: 'string1 string1 string1'
, foo: false
, bar: false
}
, { name: 'Ron Duluth'
, custNumber: '8812654434'
, sneak: 'string2 string2 string2'
, foo: false
, bar: false
}
, { name: 'Jimmy Dawson'
, custNumber: '8908198230'
, sneak: 'string3 string3 string3'
, foo: false
, bar: false
}
]

console.log (searchAll ("81", result))
// [ { custNumber: '8812654434', ... }
// , { custNumber: '8908198230', ... }
// ]

console.log (searchAll ("Du", result))
// [ { name: "Ron Duluth", ... } ]

console.log (searchAll ("zzz", result))
// []

不区分大小写的搜索

上面,我们的 search 函数使用了 v .includes (query) 但因为我们使用的是高阶函数,所以我们可以使行为尽可能具体我们想要。

searchAll 为例,我们可以如下更改

const searchAll = (query = "", data = {}) =>
Array.from
( deepFindAll
( o =>
Object.values (o) .some (v =>
<del>String (v) === v && v .includes (query))</del>
String (v) === v
<b>&& v .toLowerCase () .includes (query .toLowerCase ()))</b>
, data
)
)

但这让我们的功能变得一团糟。是时候再抽象一点,并通过给我们的意图命名来解释我们在做什么

const anyString = f => o =>
Object.values (o) .some (v =>
String (v) === v && f (v))

const caseInsenstiveMatch = (x, y) =>
x.toLowerCase () .includes (y.toLowerCase ())

const searchAll = (query = "", data = {}) =>
Array.from
( deepFindAll
( <b>anyString (v =>
caseInsenstiveMatch (v, query))</b>
, data
)
)

隔离行为和定义单独的函数是编写好的程序的重要部分。并排显示 searchsearchAll 突出了这种重要性。新的助手 anyStringcaseInsensitiveSearch 使代码清晰,但也使在需要时重用行为变得更容易。

const search = (query = "", data) =>
deepFind
( anyString (v =>
caseInsenstiveMatch (v, query))
, data
)

const searchAll = (query = "", data = {}) =>
Array.from
( deepFindAll
( anyString (v =>
caseInsenstiveMatch (v, query))
, data
)
)

对比图

高阶函数有各种各样的用途来保持我们的代码简洁和描述性。下面,我们定义了 matchlower 的极其简单的版本。然后使用 contramap,我们将我们的程序整合在一起。

这里强调的是每个功能的简单性。一个简单的函数更容易测试,更容易调试,也更容易与其他简单函数结合。 Unix 哲学,"Do one thing and do it well" 现在应该在你耳边响起

const contramap = (f, g) =>
(x, y) => f (g (x), g (y))

<b>const match = (x = "", y = "") =>
x .includes (y)

const lower = (x = "") =>
x .toLowerCase ()

const caseInsenstiveMatch =
contramap (match, lower)</b>

const anyString = (f) => (o = {}) =>
Object.values (o) .some (v =>
String (v) === v && f (v))

const searchAll = (query = "", data = {}) =>
Array.from
( deepFindAll
( anyString (v =>
caseInsenstiveMatch (v, query))
, data
)
)

Contramap 解锁了其他可能不会立即显现的能力。如果您感兴趣,我推荐 Brian Lonsdorf 的 Monoidal Contravariant Functors are actually useful!。不要让标题吓到你;作者有使这些东西变得简单的诀窍。

关于javascript - 在对象数组中,返回任何值与特定字符串匹配的对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50538060/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com