根据另一个数组过滤对象数组

时间:2020-08-13 13:53:43

标签: javascript typescript

我有一个源数组和目标数组,基于目标数组需要更新源数组

sourceAry = [{name:'Label1', value: 'label1', children:[{name:'Ammu'},{name:'Rahual'},{name:'Anu'}]},
{name:'Label2', value: 'label2', children:[{name:'Hari'},{name:'Tom'}]},
];

targetAry = [{name:'Label1', value: 'label1', children:[{name:'Anu'}]},
{name:'Label2', value: 'label2', children:[{name:'Hari'},{name:'Tom'}]},
];

resultAry = [{name:'Label1', value: 'label1', children:[{name:'Ammu'},{name:'Rahual'}]}
]},
];

我尝试的代码

let resultAry = sourceAry.map((obj) => {
      obj.children.map((elem) =>{
        targetAry.filter(parent => parent.children.filter((el) => {
          el.name !== elem.name}))
      })
    })
    console.log(resultAry, 'NEW', list);

2 个答案:

答案 0 :(得分:1)

Ciao,尝试这样的事情:

    class ProfileCus: UIViewController {
    
        // Labels to display data
        @IBOutlet weak var nameLabel: UILabel!
        @IBOutlet weak var surnameLabel: UILabel!
        @IBOutlet weak var emailLabel: UILabel!
        @IBOutlet weak var contactLabel: UILabel!
        
        // Reference to customer collection in Firestore
        private var  customerRefCollection: CollectionReference!
        
        // Customer Object
        private var customer: Customer?
        
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            // Do any additional setup after loading the view.
            
            customerRefCollection = Firestore.firestore().collection("customers")
            
            nameLabel.text = customer?.name
            surnameLabel.text = customer?.surname
            emailLabel.text = customer?.email
            contactLabel.text = customer?.contactNo
            
        }
        
// This function notifies the view controller that the view is about to load so it is best to acquire the data in here before the view loads so that it will be ready to display.

        override func viewWillAppear(_ animated: Bool) {
            // Get the current user ID
            let userID = Auth.auth().currentUser?.uid
            // Locate the user information on Firestore
            customerRefCollection.document(userID!).getDocument { (snapshot, error) in
                if let err = error {
                    debugPrint("Error fetching documents: \(err)")
                }
                else {
                    // Ensure that if there's nothing in the document that the function returns
                    guard let snap = snapshot else {return}
                    // Parse the data to the customer model
                    let data = snap.data()
                    
                    let name = data?["name"] as? String ?? ""
                    let surname = data?["surname"] as?  String ?? ""
                    let email = data?["email"] as? String ?? ""
                    let contact = data?["contact no"] as? String ?? ""
                    // Create the customer and pass it to the global variable
                    let cus = Customer(name: name, surname: surname, contactNo: contact, email: email)
                    self.customer = cus
                }
            }
        }
    }

我根据sourceAry = [{name:'Label1', value: 'label1', children:[{name:'Ammu'},{name:'Rahual'},{name:'Anu'}]}, {name:'Label2', value: 'label2', children:[{name:'Hari'},{name:'Tom'},{name:'Ammu'},{name:'Rahual'},{name:'Anu'}]}, {name:'Label3', value: 'label3', children:[{name:'Ammu'},{name:'Rahual'},{name:'Anu'}]} ]; targetAry = [{name:'Label1', value: 'label1', children:[{name:'Anu'}]}, {name:'Label2', value: 'label2', children:[{name:'Hari'},{name:'Tom'}]}, ]; let result = []; sourceAry.forEach(source => { let filter = targetAry.filter(target => target.name === source.name) if (filter.length > 0) { let filterchildren = source.children.filter(a => !filter[0].children.map(b=>b.name).includes(a.name)); if (filterchildren.length > 0) { let resultobj = source; resultobj.children = filterchildren; result.push(resultobj); } } else result.push(source); }) console.log(result)的名称过滤了targetAry。然后减去带有sourceAry的子元素,最后推入.filter(a => !filter[0].children.map(b=>b.name).includes(a.name));数组中找到的元素。

答案 1 :(得分:1)

您可以从简化一些功能入手:

const indexBy = (f, data) => data.reduce((acc, x) => Object.assign(acc, { [f(x)]: x }), {})

const remove = (keyFn, dataToRemove, from) => {
  const dataToRemoveIndexed = indexBy(keyFn, dataToRemove);
  return from.filter(it => !(keyFn(it) in dataToRemoveIndexed));
}

我们在此处引入indexBy,以使删除为O(m + n),而不是O(m ^ 2)(如果要检查的集合中有很多项)

然后您可以像这样使用它:

const targetIndexed = indexBy(it => it.name, targetAry);

const result = sourceAry.map(
  it => ({ 
    ...it, 
    children: remove(
      it => it.name, 
      (targetIndexed[it.name] || {}).children || [],
      it.children
    )
  })
)

因此它会为您带来以下结果:

[
 {"name":"Label1","value":"label1","children":[{"name":"Ammu"}, {"name":"Rahual"}]},
 {"name":"Label2","value":"label2","children":[]}
]

如果您还想删除带有空children的项目,则可以将其过滤掉:result.filter(it => it.children.length > 0)