javascript - В массиве объектов возвращает объекты, где ЛЮБОЕ значение соответствует определенной строке - PullRequest
0 голосов
/ 26 мая 2018

Я внедряю функцию поиска в свое приложение.Результаты поиска в пользовательском интерфейсе возвращаются на основе массива объектов.По сути, я пытаюсь перебрать значения name, custNumber и sneak в каждом объекте и вернуть только те объекты, которые содержат значение, содержащее строку (сгенерированное из панели поиска пользователей).Идея состоит в том, что пользователи могут искать что-нибудь в объекте и давать правильные результаты

вот мой массив

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())
})

Очевидная проблема здесь в том, что это только возврат объектов, основанных на значении имени.Однако он мне нужен для сравнения значений name, custNumber и sneak в каждом объекте с поиском пользователей.Я пробовал методы forEach, object.values ​​и object.entries и не смог заставить их работать.Любая помощь здесь очень ценится!

Ответы [ 5 ]

0 голосов
/ 18 февраля 2019

Попробуйте

let search= result.filter(x=> ['name','custNumber','sneak']
     .reduce((o,a)=> x[a].toLowerCase().includes(query.toLowerCase())||o, false) );

Где query ваш searchbarVal.toLowerCase()

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,
}
]

let query="89"; // searchbarVal.toLowerCase()

let search= result.filter(x=> ['name','custNumber','sneak'].reduce((o,a)=> x[a].toLowerCase().includes(query.toLowerCase())||o, false) );

console.log(search);
0 голосов
/ 26 мая 2018

рекурсивный поиск

Это тема, о которой я писал недавно .Вот общий deepFind.Он работает рекурсивно и может «искать» любое входное значение.

Ниже мы создадим простой набор data, а затем покажем, как 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

Ниже мы кодируем нашобщая функция сопоставления строк search с использованием deepFind

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
        )
    )

Изоляция поведения и определение отдельных функций - важная часть написания хороших программ.Отображение search и searchAll рядом подчеркивает эту важность.Новые помощники anyString и caseInsensitiveSearch хранят код в чистоте, но также облегчают повторное использование поведения при необходимости.

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

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

contramap

Функции высшего порядка могут использоваться для сохранения чистоты и описательности нашего кода.Ниже мы определяем простейшие версии match и lower.Затем, используя contramap, мы объединяем нашу программу.

Акцент здесь делается на простоте каждой функции.Простую функцию легче тестировать, легче отлаживать и легче комбинировать с другими простыми функциями.Философия Unix, «Делай одно и делай это хорошо» должна звучать в твоих ушах прямо сейчас

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 открывает другие силы, которые могут бытьсразу видноЕсли вас это интересует, я рекомендую моноидальные контравариантные функторы действительно полезны! Брайана Лонсдорфа.Не позволяйте названию напугать вас;у автора есть ловкость, чтобы сделать это легко.

0 голосов
/ 26 мая 2018

Вы можете перебрать объект и попытаться сделать что-то вроде следующего:

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,
}
];

var searchStr = "Donna";

console.log(searchObj(searchStr));

function searchObj(search){
  var searchResult = [];
  for(var obj in result){
      var str = JSON.stringify(result[obj]);
      if(str.indexOf(search) > 0){
        searchResult.push(result[obj]);
      }
  }
  return searchResult;
}
0 голосов
/ 26 мая 2018
function searchObj(search){
  let answer = [];
  result.forEach(re => {
    if(JSON.stringify(re).indexOf(search) > 0){
      answer.push(re)
    }
  });
  return answer;
}

Перебрать все элементы массива, преобразовать их в строку и использовать indexOf, чтобы найти критерии соответствия.Таким образом, вы можете сохранить несколько циклов, не повторяя каждый ключ каждого элемента.

0 голосов
/ 26 мая 2018

'Некоторые' в вашем фильтре могут сработать, проверив все ключи.

return result.filter(convo => {
  return Object.keys(convo).some(key => {
     return convo[key].toLowerCase().includes(searchbarVal.toLowerCase())
  })
})
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...