0

I have such two arrays of objects:

const first = [{text: 'sometext1', applicable: true}, {text: 'sometext2', applicable: false}, {text: 'sometext3', applicable: true}];

const second = [{text: 'sometext1', applicable: true}, {text: 'sometext2', applicable: true}];

As a result I want to get such array:

const result = [{text: 'sometext1', applicable: true}, {text: 'sometext2', applicable: true}, {text: 'sometext3', applicable: true}];

so => just add to second array all non-existing items from first array, filtered by 'text' key.

is it possible to do via reducers? or maybe any better way?

5 Answers 5

1

Just iterate over first array and check whether each item present in second array or not, if not present then push in to second array.

first.forEach((item) => {
    const index = second.findIndex((st) => st.text === item.text);
    if(index < 0) {
        second.push(item);
    }
})
Sign up to request clarification or add additional context in comments.

3 Comments

it's a dirty way :)
Map we can't use, as it'll return new array. Even if we use reduce on 'first' array and pass 'second' array as accumulator, you have to check each element is present in second array or not.
How about, first iterating over 'second' and storing text's in map, then iterate over 'first' array and check each item is present in map or not and then push. Which will avoid finding of elements every time. We need to traverse each array once. So complexity also less.
0

You can use maps

const first = [{text: 'sometext1', applicable: true}, {text: 'sometext2', applicable: false}, {text: 'sometext3', applicable: true}];

const second = [{text: 'sometext1', applicable: true}, {text: 'sometext2', applicable: true}];

var a=second.map((e)=>e.text);
first.map((e)=>{a.includes(e.text)?false:second.push(e)})
console.log(second);

Comments

0

You can use a filter to remove duplicates using a key.

function concatAndRemoveDuplicates(arr1, arr2) {
  return arr1.concat(
    arr2.filter((o) => !arr2.map((x) => x.text).includes(o.text)),
  );
}

1 Comment

wrong, it should pick up all items like in my result, your solution will set second item with false applicable
0

You could do

const first = [{text: 'sometext1', applicable: true}, {text: 'sometext2', applicable: false}, {text: 'sometext3', applicable: true}];

const second = [{text: 'sometext1', applicable: true}, {text: 'sometext2', applicable: true}];

const results = [...second, ...first.filter(({text:firstText})=>!second.find(({text})=>text===firstText))]

console.log(results);

but it does not clone the objects.

Comments

0

As per your tags, I see that you have the possibility to use ES6 so you could do it with Set for example to have unique values in your array and then filter it:

const grouped = [...second, ...first];
const result = 
   [ ...new Set(grouped.map(({ text}) => text))]
   .map(text => grouped.find(obj => obj.text === text))

Tests

Here is a link with tests: enter image description here

3 Comments

not sure that it's working for 100% cases, sometimes it's taking wrong object, so applicable value is ovewrriten from first - what is wrong
probably due to sorting order
@brabertaser19 Could you confirm it with examples? I will update the answer with tests. Please feel free to add your tests and point the issue

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.