0

I have this initial array and want to extract the repeating flights based on from.flightNo and to.flightNo

const myArray = [
        { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 23 },
        { from: { flightNo: 'A12' }, to: { flightNo: 'B45' }, code: 22 },
        { from: { flightNo: 'A12' }, to: { flightNo: 'B52' }, code: 21 },
        { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 20 },
        { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 25 },
        { from: { flightNo: 'A15' }, to: { flightNo: 'B69' }, code: 24 },
        { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 26 },
      ];

  result: 
 [
    { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 23 },
    { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 20 },
    { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 25 },
    { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 26 },
  ]

I wrote this but I can only get the first repeating one and doesn't look very pretty.

  const duplicates = myArray
    .map((item) => {
      let count = 0;
      for (let i = 0; i < myArray.length; i++) {
        if (count > 1) {
          count = 0;
          return item;
        }
        if (
          myArray[i]?.from?.flightNo == item?.from?.flightNo &&
          myArray[i]?.to?.flightNo == item?.to?.flightNo
        )
          count++;
      }
    })
    .filter((notUndefined) => notUndefined !== undefined);

Any suggestions?

4 Answers 4

2
  1. Create a Map out of the array whose key is from.flightNo + to.flightNo and value is an array of all the objects that match this from.flightNo + to.flightNo

  2. Keep only the values that have length greater than 1.

const myArray = [
  { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 23 },
  { from: { flightNo: 'A12' }, to: { flightNo: 'B45' }, code: 22 },
  { from: { flightNo: 'A12' }, to: { flightNo: 'B52' }, code: 21 },
  { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 20 },
  { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 25 },
  { from: { flightNo: 'A15' }, to: { flightNo: 'B69' }, code: 24 },
  { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 26 },
];

console.log(
  Array.from(
    myArray.reduce(
      (m, o) =>
        m.set(
          o.from.flightNo + o.to.flightNo,
          (m.get(o.from.flightNo + o.to.flightNo) || []).concat(o)
        ),
      new Map()
    )
  ).reduce((a, [k, v]) => (v.length > 1 ? a.concat(v) : a), [])
);

Based on the discussions below in the comment I've updated my code to the following:

const myArray = [
  { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 23 },
  { from: { flightNo: 'A12' }, to: { flightNo: 'B45' }, code: 22 },
  { from: { flightNo: 'A12' }, to: { flightNo: 'B52' }, code: 21 },
  { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 20 },
  { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 25 },
  { from: { flightNo: 'A15' }, to: { flightNo: 'B69' }, code: 24 },
  { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 26 },
];

const result = Array.from(
  myArray.reduce(
    (m, o) => (
      m.has(o.from.flightNo + "-" + o.to.flightNo)
        ? m.get(o.from.flightNo + "-" + o.to.flightNo).push(o)
        : m.set(o.from.flightNo + "-" + o.to.flightNo, [o]),
      m
    ),
    new Map()
  )
)
  .reduce((a, [k, v]) => (v.length > 1 && a.push(v), a), [])
  .flat();

console.log(result);

Sign up to request clarification or add additional context in comments.

12 Comments

Nice. Same comment about + as I made for Ravikumar's answer. For the rest it is very functional programming style (+1). Downside is that arrays are copied over and over again, and this can give a worst case time complexity of O(n²) -- when all flights have the same pair of codes.
@trincot I didn't get how is it an O(n2) solution. myArray should be reduced to a Map in O(n) time then Array.from() that Map should also take O(n) time and the final reduce should also take O(n) time. And all these happen independently so there's no nesting, so why do you say its O(n2)? Please help!
Oh you mean to say when I spread the array, that is where the problem lies, right @trincot?
That is really engine dependent. I just ran that second snippet there on FF, and concat turns out to be faster. Most important though is that they both have a O(n+m) time complexity (m for the second array, if used to join two arrays)
Yes, with push you resolve the complexity issue. However, the comment about adding the two codes (that I made to another answer) still holds, and (partly?) explains why your code runs faster, since in my code I took precautions against such code mixup.
|
2

You can create a map, keyed by the flight number pairs (and use JSON.stringify to stringify that pair), with an empty array for each key. Then iterate the data to populate those arrays.

Finally extract those sub arrays that have more than one element, and flatten the result:

const myArray = [{ from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 23 },{ from: { flightNo: 'A12' }, to: { flightNo: 'B45' }, code: 22 },{ from: { flightNo: 'A12' }, to: { flightNo: 'B52' }, code: 21 },{ from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 20 },{ from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 25 },{ from: { flightNo: 'A15' }, to: { flightNo: 'B69' }, code: 24 },{ from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 26 },];

let map = new Map(myArray.map(o => [JSON.stringify([o.from.flightNo, o.to.flightNo]), []]));
for (let o of myArray) map.get(JSON.stringify([o.from.flightNo, o.to.flightNo])).push(o);
let result = [...map.values()].filter(arr => arr.length > 1).flat();

console.log(result);

3 Comments

I dont think its just the flight numbers - the code feeds into the duplicate too
I verified the output, @Jamiec, and it is identical to what the OP expects. Did I miss something?
@trincot If you could spare some time and review my solution, it would be really helpful.
1

You can achieve this by grouping all the elements by unique key then filter out unnecessary elements by group length

const myArray = [
        { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 23 },
        { from: { flightNo: 'A12' }, to: { flightNo: 'B45' }, code: 22 },
        { from: { flightNo: 'A12' }, to: { flightNo: 'B52' }, code: 21 },
        { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 20 },
        { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 25 },
        { from: { flightNo: 'A15' }, to: { flightNo: 'B69' }, code: 24 },
        { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 26 },
      ];
      
      
      function getDuplicates(myArray) {
      //grouping by unique key
       return Object.values(myArray.reduce((acc, r) => {
            const key = r.from.flightNo+r.to.flightNo;
            if (!acc[key]) {
              acc[key] = [];
            }
            acc[key].push(r);
            return acc;
      }, {}))
      // merging all duplicated items
      .reduce((acc, list) => list.length > 1 ? acc.concat(list) : acc, []);
      }
      
      console.log(getDuplicates(myArray));

4 Comments

Be careful here: if one flight is from "A1B" to "2C3" and another is from "A1" to "B2C3", then they will be considered the same.
I don't think, as @arled clearly mentioned that he need duplicated flights exactly matching from and to with same flightNo with the same order. Agreed, need to be careful (rewrite the matching logic) if what you said is the criteria.
@Ravikumar You can simply add some special character between the strings like "A1B" + "&" + "2C3".
@SomShekharMukherjee why do you want that? do you see any additional gain out of it?
0

You could loop your flights and make a new code with the from and to flight numbers. Then check this string if it's already added. If not, add to result.

const myArray = [
        { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 23 },
        { from: { flightNo: 'A12' }, to: { flightNo: 'B45' }, code: 22 },
        { from: { flightNo: 'A12' }, to: { flightNo: 'B52' }, code: 21 },
        { from: { flightNo: 'A11' }, to: { flightNo: 'B11' }, code: 20 },
        { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 25 },
        { from: { flightNo: 'A15' }, to: { flightNo: 'B69' }, code: 24 },
        { from: { flightNo: 'A14' }, to: { flightNo: 'B44' }, code: 26 },
];

var codes = [];
var result = [];

myArray.forEach(function (flight) {
  var newCode = flight.from.flightNo + flight.to.flightNo;
  if (codes.indexOf(newCode) === -1) {
    codes.push(newCode);
   }
  else {
   result.push(flight)
   }


});

console.log(result)

1 Comment

I didn't downvote, but the OP expects 4 results, not 2. Secondly, indexOf represents a scan over an array, which makes the time complexity O(n²), while O(n) is possible. Still, I don't think that is worth a downvote, so +1

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.