通过匹配父级或子级中的关键字来过滤嵌套数组

时间:2018-07-25 07:34:42

标签: javascript lodash

我需要通过匹配关键字来过滤嵌套数组。它必须返回与父级或其子项之一的name属性匹配的所有对象,并且还要过滤其子项。

示例:

[
  {
    "name": "abc",
    "children": [
      { "name": "abcd" },
      { "name": "efg" }
    ]
  },
  {
    "name": "hjk",
    "children": [
      { "name": "lmn" },
      { "name": "opq" }
    ]
  },
  {
    "name": "xyz",
    "children": [
      { "name": "lmn" },
      { "name": "abcdef" }
    ]
  }
]

如果文本输入为“ ab”,则它必须返回:

[
  {
    "name": "abc",
    "children": [
      { "name": "abcd" }
    ]
  },
  {
    "name": "xyz",
    "children": [
      { "name": "abcdef" }
    ]
  }
]

(它与父代OR或至少一个子代匹配,但返回但有父代和子代)

现在,我只能像这样过滤父母:

filteredArray = _.filter(array, (parent) => {
    return _.includes(_.toLower(parent.name), _.toLower(filterText));
});

我该如何修改它以便也过滤孩子?

编辑: 父级可以有空或无子级数组。

4 个答案:

答案 0 :(得分:1)

恕我直言,您可以使用Array#reduce()方法执行以下操作:

arr = [{"name":"abc","children":[{"name":"abcd"},{"name":"efg"}]},{"name":"hjk","children":[{"name":"lmn"},{"name":"opq"}]},{"name":"xyz","children":[{"name":"lmn"},{"name":"abcdef"}]}, {"name": "xyz"}]

var input = "ab"
filteredArr = arr.reduce((accum, ele) => {
  var obj = {};
  ele['children'] && ele['children'].forEach(e => {
    if (e['name'].includes(ele['name']) || e['name'].includes(input)) {
      obj['name'] = ele['name'];
      obj['children'] ? (obj['children'].push(e)) : (obj['children'] = [], obj['children'].push(e))
    }
  })
  if (Object.keys(obj).length > 0) accum.push(obj);
  return accum;
}, [])

console.log(filteredArr);

答案 1 :(得分:1)

为每个元素检查名称并过滤其子元素,如果其中一个为真,则将具有已过滤子元素的元素推入新数组

const data = [{"name": "abc", "children": [{ "name": "abcd" }, { "name": "efg" }  ] }, {"name": "hjk","children": [{ "name": "lmn"},  { "name": "opq" }  ]}, { "name": "xyz","children": [{ "name": "lmn"
},{"name": "abcdef" } ] }, {"name": "abc"}, {"name": "abc", children: []}];

const res = data.reduce((acc, a) => {
  const ch = a.children && a.children.filter(b => b.name.includes('ab'));
  if(ch && ch.length) acc.push({...a, children: ch});
  else if(a.name.includes('ab')) acc.push({ name: a.name });
  return acc;
}, []);

console.log(res);

答案 2 :(得分:1)

lodash中没有真正的需求。 #nodash!只是现代香草JS:

const regExp = new RegExp(filterText, 'i');

const result = array.reduce((acc, { name, children = [] }) => {
  const next = children.filter(child => child.name.match(regExp));

  if (name.match(regExp) || next.length > 0) {
    acc.push({ name, children: next });
  }

  return acc;
}, []);
如果找不到子字符串,

name.match(regExp)将返回null

children = []处理parent没有孩子的情况。

另外,请注意,使用RegExp检查子字符串应该比执行多次转换和查找(例如toLowerincludes)要快得多。

这是工作中的repl with your example

答案 3 :(得分:0)

 I/OpenGLRenderer: Initialized EGL, version 1.4
D/OpenGLRenderer: Enabling debug mode 0
I/Timeline: Timeline: Activity_idle id: android.os.BinderProxy@2ebe9688 time:2777009
D/ROOT: Root access requested 
D/Camera2VideoFragment: tryAcquire
I/CameraManagerGlobal: getCameraService: Reconnecting to camera service
E/Camera2VideoFragment: Couldn't find any suitable preview size
D/Camera2VideoFragment: openCamera: Intialising New MediaRecorder.
D/Camera2VideoFragment: openCamera: Manager.openCamera called here: 1532504895664
I/CameraManager: Using legacy camera HAL.
D/Camera2VideoFragment: onOpened: This is called: 1532504896165
I/CameraDeviceState: Legacy camera service transitioning to state CONFIGURING
I/RequestThread-0: Configure outputs: 1 surfaces configured.
D/Camera: app passed NULL surface
I/CameraDeviceState: Legacy camera service transitioning to state IDLE
I/RequestQueue: Repeating capture request set.
W/LegacyRequestMapper: convertRequestMetadata - control.awbRegions setting is not supported, ignoring value
W/LegacyRequestMapper: convertRequestToMetadata - Ignoring android.lens.focusDistance false, only 0.0f is supported
I/CameraDeviceState: Legacy camera service transitioning to state CAPTURING
E/BufferQueueProducer: [unnamed-8823-1] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=6 undequeued=0)
E/BufferQueueProducer: [unnamed-8823-1] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=5 undequeued=1)
D/Camera2VideoFragment: onClick: NUM_OF_RESTARTS click: 0
I/RequestQueue: Repeating capture request cancelled.
I/CameraDeviceState: Legacy camera service transitioning to state CONFIGURING
I/RequestThread-0: Configure outputs: 2 surfaces configured.
D/Camera: app passed NULL surface
I/CameraDeviceState: Legacy camera service transitioning to state IDLE
I/RequestQueue: Repeating capture request set.
W/LegacyRequestMapper: convertRequestMetadata - control.awbRegions setting is not supported, ignoring value
W/LegacyRequestMapper: convertRequestToMetadata - Ignoring android.lens.focusDistance false, only 0.0f is supported
V/RenderScript: 0xb7cfa0a0 Launching thread(s), CPUs 4
E/BufferQueueProducer: [unnamed-8823-2] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=6 undequeued=0)
I/CameraDeviceState: Legacy camera service transitioning to state CAPTURING
E/BufferQueueProducer: [unnamed-8823-2] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=5 undequeued=1)
D/Camera2VideoFragment: MediaRecorder onInfo: 801 extra: 0
D/Camera2VideoFragment: run: calling onVideoInfo here: 1532504954189
                        onVideoInfo: what: 801 extra: 0
                        onVideoInfo: Thread Name: main
                        onVideoInfo: MAX FILE SIZE APPROACHING
                        onVideoInfo: Calling stopRecordingVideo: 1532504954189
D/Camera2VideoFragment: restartRecordingVideo: Stoping Video From restart: 1532504954193
                        stopRecordingVideo: Stop Video Recording
                        stopRecordingVideo: About to call mMediaRecorder.stop()
W/Adreno-EGLSUB: <DequeueBuffer:736>: dequeue native buffer fail: No such device, buffer=0x0, handle=0x0
W/Adreno-EGL: <qeglDrvAPI_eglSwapBuffers:3709>: EGL_BAD_SURFACE
E/CameraDeviceGLThread-0: Received exception on GL render thread: 
                          java.lang.IllegalStateException: swapBuffers: EGL error: 0x300d
                              at android.hardware.camera2.legacy.SurfaceTextureRenderer.checkEglError(SurfaceTextureRenderer.java:530)
                              at android.hardware.camera2.legacy.SurfaceTextureRenderer.swapBuffers(SurfaceTextureRenderer.java:523)
                              at android.hardware.camera2.legacy.SurfaceTextureRenderer.drawIntoSurfaces(SurfaceTextureRenderer.java:729)
                              at android.hardware.camera2.legacy.GLThreadManager$1.handleMessage(GLThreadManager.java:105)
                              at android.os.Handler.dispatchMessage(Handler.java:98)
                              at android.os.Looper.loop(Looper.java:135)
                              at android.os.HandlerThread.run(HandlerThread.java:61)
I/CameraDeviceState: Legacy camera service transitioning to state ERROR
D/Camera2VideoFragment: stopRecordingVideo: Done mMediaRecorder.stop()
                        stopRecordingVideo: Reset mMediaRecorder
                        stopRecordingVideo: Release mMediaRecorder
D/Camera2VideoFragment: stopRecordingVideo: Closing Camera: 1532504954421
                        closeCamera: mCameraDevice.close() called here.
E/RequestThread-0: Timed out while waiting for request to complete.
W/CaptureCollector: Preview buffers dropped for request: 1
E/CameraDeviceState: Cannot receive result while in state: 0
                     Cannot receive result while in state: 0
E/CameraDeviceState: Cannot receive result while in state: 0
W/MessageQueue: Handler (android.graphics.SurfaceTexture$1) {63c0706} sending message to a Handler on a dead thread
                java.lang.IllegalStateException: Handler (android.graphics.SurfaceTexture$1) {63c0706} sending message to a Handler on a dead thread
                    at android.os.MessageQueue.enqueueMessage(MessageQueue.java:325)
                    at android.os.Handler.enqueueMessage(Handler.java:631)
                    at android.os.Handler.sendMessageAtTime(Handler.java:600)
                    at android.os.Handler.sendMessageDelayed(Handler.java:570)
                    at android.os.Handler.sendEmptyMessageDelayed(Handler.java:534)
                    at android.os.Handler.sendEmptyMessage(Handler.java:519)
                    at android.graphics.SurfaceTexture.postEventFromNative(SurfaceTexture.java:368)
E/BufferQueueProducer: [unnamed-8823-2] cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer: [unnamed-8823-2] cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer: [unnamed-8823-2] cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer: [unnamed-8823-2] cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer: [unnamed-8823-2] cancelBuffer: BufferQueue has been abandoned
D/Camera2VideoFragment: stopRecordingVideo: Opening Camera: 1532504958414
D/Camera2VideoFragment: tryAcquire
E/Camera2VideoFragment: Couldn't find any suitable preview size
D/Camera2VideoFragment: openCamera: Intialising New MediaRecorder.
                        openCamera: Manager.openCamera called here: 1532504958422
I/CameraManager: Using legacy camera HAL.
D/Camera2VideoFragment: onVideoInfo: came back here after restarting video recording: 1532504958920
                        run: returned here after onVideoInfo: 1532504958920
D/Camera2VideoFragment: onError: This is called with error: 1 at: 1532504958924
                        onError: cameraDevice.close() is called here: 1532504958924
D/Camera2VideoFragment: onClosed: Camera Closed: 1532504958954
D/Camera2VideoFragment: onOpened: This is called: 1532504958991
I/CameraDeviceState: Legacy camera service transitioning to state CONFIGURING
I/RequestThread-0: Configure outputs: 2 surfaces configured.
D/Camera: app passed NULL surface
I/CameraDeviceState: Legacy camera service transitioning to state IDLE
D/Camera2VideoFragment: onPause: In onPause
I/RequestQueue: Repeating capture request set.
W/LegacyRequestMapper: convertRequestMetadata - control.awbRegions setting is not supported, ignoring value
                       convertRequestToMetadata - Ignoring android.lens.focusDistance false, only 0.0f is supported
W/IInputConnectionWrapper: showStatusIcon on inactive InputConnection
E/BufferQueueProducer: [unnamed-8823-3] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=6 undequeued=0)
I/CameraDeviceState: Legacy camera service transitioning to state CAPTURING
E/BufferQueueProducer: [unnamed-8823-0] dequeueBuffer: BufferQueue has been abandoned
W/Adreno-EGLSUB: <DequeueBuffer:736>: dequeue native buffer fail: No such device, buffer=0x0, handle=0x0
W/Adreno-EGL: <qeglDrvAPI_eglSwapBuffers:3709>: EGL_BAD_SURFACE
E/CameraDeviceGLThread-0: Received exception on GL render thread: 
                          java.lang.IllegalStateException: swapBuffers: EGL error: 0x300d
                              at android.hardware.camera2.legacy.SurfaceTextureRenderer.checkEglError(SurfaceTextureRenderer.java:530)
                              at android.hardware.camera2.legacy.SurfaceTextureRenderer.swapBuffers(SurfaceTextureRenderer.java:523)
                              at android.hardware.camera2.legacy.SurfaceTextureRenderer.drawIntoSurfaces(SurfaceTextureRenderer.java:729)
                              at android.hardware.camera2.legacy.GLThreadManager$1.handleMessage(GLThreadManager.java:105)
                              at android.os.Handler.dispatchMessage(Handler.java:98)
                              at android.os.Looper.loop(Looper.java:135)
                              at android.os.HandlerThread.run(HandlerThread.java:61)
I/CameraDeviceState: Legacy camera service transitioning to state ERROR
D/Camera2VideoFragment: onError: This is called with error: 1 at: 1532504959666
D/Camera2VideoFragment: onError: cameraDevice.close() is called here: 1532504959667
E/BufferQueueProducer: [unnamed-8823-3] dequeueBuffer: min undequeued buffer count (2) exceeded (dequeued=5 undequeued=1)
E/RequestThread-0: Timed out while waiting for request to complete.
W/CaptureCollector: Preview buffers dropped for request: 0
E/CameraDeviceState: Cannot receive result while in state: 0
                     Cannot receive result while in state: 0
E/CameraDeviceState: Cannot receive result while in state: 0
E/BufferQueueProducer: [unnamed-8823-3] queueBuffer: BufferQueue has been abandoned
E/BufferQueueProducer: [unnamed-8823-3] dequeueBuffer: BufferQueue has been abandoned
E/BufferQueueProducer: [unnamed-8823-3] cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer: [unnamed-8823-3] cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer: [unnamed-8823-3] cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer: [unnamed-8823-3] cancelBuffer: BufferQueue has been abandoned
E/BufferQueueProducer: [unnamed-8823-3] cancelBuffer: BufferQueue has been abandoned
D/Camera2VideoFragment: onClosed: Camera Closed: 1532504963772
W/CameraCaptureSession: Session 1: The camera device was already closed: 
                        java.lang.IllegalStateException: CameraDevice was already closed
                            at android.hardware.camera2.impl.CameraDeviceImpl.checkIfCameraClosedOrInError(CameraDeviceImpl.java:1482)
                            at android.hardware.camera2.impl.CameraDeviceImpl.stopRepeating(CameraDeviceImpl.java:677)
                            at android.hardware.camera2.impl.CameraCaptureSessionImpl.close(CameraCaptureSessionImpl.java:328)
                            at android.hardware.camera2.impl.CameraCaptureSessionImpl.finalize(CameraCaptureSessionImpl.java:561)
                            at java.lang.Daemons$FinalizerDaemon.doFinalize(Daemons.java:191)
                            at java.lang.Daemons$FinalizerDaemon.run(Daemons.java:174)
                            at java.lang.Thread.run(Thread.java:818)