2

In the initial stage, i have an object array:

[
 { type: 'all' },
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit'},
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit' },
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit' },
 { type: 'fruit' }
]

I want to insert :

1) object: {type: 'toys'} in every 5 items with type: all

2) object: {type: 'clothes'} in every 2 items with type: 'fruit'

Expected Result:

[
 { type: 'all' },
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit'},
 { type: 'all' },
 { type: 'all' },
 { type: 'toys' },
 { type: 'fruit' },
 { type: 'clothes' },
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit' },
 { type: 'fruit' },
 { type: 'clothes' }
]

How can i implement this function ? I tried to forEach to add the items, but after pushing an item, the array_demo length is changed and hard to measure which is the next original item of the list.

array_demo.forEach((item, index) => {
  array_demo.push({type: 'demo'});
  console.warn(index);
});
1
  • Do it on another array instead of doing it in place Commented Jan 24, 2018 at 10:31

7 Answers 7

1

You could count the occurence and insert if found the right number of apperance and add a new object into the array.

For counting and keeping the logic, this appoach uses an object with the wanted types as keys and all other values, like size and type for inserting.

{
    all: {
        count: 0,
        size: 5,
        type: 'toys'
    },
    fruit: {
        count: 0,
        size: 2,
        type: 'clothes'
    }
}

var array = [{ type: 'all' }, { type: 'all' }, { type: 'all' }, { type: 'fruit'}, { type: 'all' }, { type: 'all' }, { type: 'fruit' }, { type: 'all' }, { type: 'all' }, { type: 'fruit' }, { type: 'fruit' }],
    types = { all: { count: 0, size: 5, type: 'toys' }, fruit: { count: 0, size: 2, type: 'clothes' } },
    type,
    i = 0;

while (i < array.length) {
    type = types[array[i].type];
    if (type && ++type.count === type.size) {
        array.splice(++i, 0, { type: type.type });
        type.count = 0;
    }               
    ++i;
}

console.log(array);
.as-console-wrapper { max-height: 100% !important; top: 0; }

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

Comments

0

You can make use of reduce and keep a count of all and fruits

const array_demo = [
 { type: 'all' },
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit'},
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit' },
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit' },
 { type: 'fruit' }
]

let all = 0;
let fruit = 0;
const newArray = array_demo.reduce((acc, item, index) => {
  if(item.type === 'all') {
     if(all === 4) {
       acc.push(item);
       acc.push({type: 'toys'})
       all = 0;
       return acc;
     } else {
       all++;
     }
  }else if(item.type === 'fruit') {
    if(fruit === 1) {
       acc.push(item);
       acc.push({type: 'clothes'})
       fruit = 0;
       return acc;
     } else {
       fruit++;
     }
    
  }
  acc.push(item);
  return acc;
  
}, []);
console.log(newArray);

Comments

0

A simple and traditional approach:

let init = [
 { type: 'all' },
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit'},
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit' },
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit' },
 { type: 'fruit' }
]

let last = [];
let allCounter = 0;
let fruitCounter = 0;

for (let type of init) {
	last.push(type);

	if (type.type == 'all' ) {
		allCounter++;
		if (allCounter == 5) {
			last.push({type:'toys'})
			allCounter = 0;
		}
	} else if (type.type == 'fruit') {
		fruitCounter++;
		if (fruitCounter == 2) {
			last.push({type: 'clothes'})
			fruitCounter = 0;
		}
	}
}

console.warn(last)

Comments

0

Other solution, same result

function insertion(my_array){
    var i=0,
        j=0,
        n=my_array.length,
        k=0;
    while(k<n){
        if(my_array[k].type=='all'){
            i++;console.log(i);
        }else if(my_array[k].type=='fruit'){
            j++;console.log(j);
        }
        if(i==5){
            k++;
            my_array.splice(k,0,{ type: 'toys' });
            i = 0;
            n++;
        }else if(j==2){
            k++;
            my_array.splice(k,0,{ type: 'clothes' });
            j = 0;
            n++;
        }
        k++;
    }
    return my_array;
}

Comments

0

var data = 
[
 { type: 'all' },
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit'},
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit' },
 { type: 'all' },
 { type: 'all' },
 { type: 'fruit' },
 { type: 'fruit' }
];

var result = [];
var allCounter = 0;
var fruitCounter = 0;
data.forEach(function(item,index){
  result.push(item);
  if(item.type == "all"){
    allCounter++;
  }
  if(item.type == "fruit"){
    fruitCounter++;
  }
  if(allCounter == 5){
    result.push({"type":"toys"});
    allCounter = 0;
  }
  if(fruitCounter == 2){
    result.push({"type":"clothes"})
    fruitCounter = 0;
  }
});

console.log(result);

Comments

0

You can Array#map the data, and use 2 outer counters (fruit, and all) to count the number of occurrences of each one. For each object that has one of the types, increment the counter, and check if it's the 2nd fruit / 5th all. If it matches the criteria return a new array with the original and the added object. Afterwards flatten all sub arrays by spreading in Array#concat.

Note: The solution uses @NinaScholz types object to make it more generic.

const data = [{"type":"all"},{"type":"all"},{"type":"all"},{"type":"fruit"},{"type":"all"},{"type":"all"},{"type":"fruit"},{"type":"all"},{"type":"all"},{"type":"fruit"},{"type":"fruit"}];

const types = {
    all: { count: 0, size: 5, type: 'toys' },
    fruit: { count: 0, size: 2, type: 'clothes' }
};

const result = [].concat(...data.map((o) => {
  const to = types[o.type];

  return !to || ++to.count % to.size ? o : [o, { type: to.type }];
}));

console.log(result);

Comments

0

Got a similar need solved with:

const concatAt = (array, predicate, value) => array.reduce(
    (c, n, idx) => {
        const at = typeof predicate === 'function' ? predicate(idx, n, array) : predicate === idx
        const newValue = typeof value === 'function' ? value(n, idx, array) : value
        return at ? [...c, n, newValue] : [...c, n]
    } , [])
const idOddIndex = n => n % 2
const isNth = nth => n => n % nth === nth - 1
const increment = n => n + 1

console.log(concatAt([0, 1, 3, 4, 6], idOddIndex, increment)) // [0, 1, 2, 3, 4, 5, 6]
concatAt([0, 1, 3, 4, 6], isNth(3), increment) // [0, 1, 3, 4, 4, 6]

I hope it will help someone.

Comments

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.