Reputation: 245
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);
});
Upvotes: 2
Views: 2924
Reputation: 784
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.
Upvotes: 0
Reputation: 386746
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; }
Upvotes: 1
Reputation: 192507
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);
Upvotes: 0
Reputation: 1369
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);
Upvotes: 0
Reputation: 712
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;
}
Upvotes: 0
Reputation: 783
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)
Upvotes: 0
Reputation: 281922
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);
Upvotes: 0