Javascript - Moving occurrences of undefined to the end of an array - javascript

I'm looking to move all occurrences of undefined to the end of an array.
So for example if my array looks like: [undefined,"bbc", "cnn"] the function will create: ["bbc", "cnn", undefined]
I have built a script that can do that:
arr = [undefined,"bbc", "cnn"]
var loopNo = 0
for (var f = 0; f < arr.length; f++) {
loopNo += 1
var keyNo = loopNo - 1
if (arr[f] === undefined){
arr.push(arr.splice(keyNo, 1)[0]);
}
}
console.log(arr)
However if undefined occurs more than once it doesn't move it - i.e [undefined , undefined, "cnn"]
How do I make it so undefined is shifted to the end of the array every-time?
Thanks.

Better way [Big O(N)]:
const shiftUndefined = (arr) => {
let duplicate = [];
for (let i = 0, len = arr.length, j = len - 1, k = 0; k <= j; i++) {
const item = arr[i];
if (item === undefined) {
duplicate[j--] = undefined;
} else {
duplicate[k++] = item;
}
}
return duplicate;
};
const arr = [undefined, "bbc", "cnn"];
const arr2 = [undefined, undefined, "cnn"];
console.log(shiftUndefined(arr)); // [ 'bbc', 'cnn', undefined ]
console.log(shiftUndefined(arr2)); // [ 'cnn', undefined, undefined ]
Keep Same ref: Big O(N)
function sameRefMove(array) {
const filtered = array.filter(Boolean);
let index = 0;
while (index < filtered.length) {
array[index] = filtered[index++];
}
while (index < array.length) {
array[index++] = undefined;
}
return array;
}
var array = [undefined, "bbc", "cnn"];
console.log(sameRefMove(array));
console.log(sameRefMove([undefined, undefined, "cnn"]));
Using reduce:
const move = (arr) => {
const [filtered, noValue] = arr.reduce(
([filtered, noValue], item) => {
if (item === undefined) noValue.push(undefined);
else filtered.push(item);
return [filtered, noValue];
},
[[], []]
);
return filtered.concat(noValue);
};
let arr = [undefined, "bbc", "cnn"];
arr = move(arr);
console.log(arr);
arr = [undefined, undefined, "cnn"];
arr = move(arr);
console.log(arr);
Just use sort if performance is not concern.
const arr = [undefined,"bbc", "cnn"]
console.log(arr.sort()) // [ 'bbc', 'cnn', undefined ]

Assuming you:
only want to move undefined to the end of an array without affecting others,
are okay with creating intermediate arrays,
here's a simple way to accomplish this, using Array.prototype.filter():
let arr = [undefined, undefined,"bbc", "cnn", "abc"];
const arrDefined = arr.filter(el => el !== undefined);
const arrUndefined = arr.filter(el => el === undefined);
arr = [...arrDefined, ...arrUndefined];
console.log('arr:', arr);
// [ "bbc", "cnn", "abc", undefined, undefined ]

You could iterate from the end and splice and push undefined values.
function move(value, array) {
var i = array.length - 1;
while (i--) {
if (array[i] === value) {
array.push(array.splice(i, 1)[0]);
}
}
return array;
}
var array = [undefined, "bbc", "cnn"];
console.log(move(undefined, array));

Related

How to I take an array and put it into another array to make a multi-dimensional array in Javascript

I want to make an array, then push arrays onto the array as elements. How do I do that?
let array3 = [];
const array1 = [1,2];
const array2 = [3,4];
array3.push(array1);
console.log(array3);
// expected [[1,2]]
array3.push(array2);
console.log(array3);
// expected [[1,2],[3,4]]
This what I am trying to make work:
const _ = {
chunk: (array, chunkSize = 1) =>{
console.log(`Original Array: ${array}` );
let chunk = [];
let chunkArr = [];
while(array.length > 0)
{
while(chunk.length < chunkSize && array.length > 0)
{
chunk.push(array.shift());
}
console.log(`Chunk: ${chunk}`);
chunkArr.push(chunk);
console.log(`Chunk Array: ${chunkArr}` );
while(chunk.length > 0)
{
chunk.pop();
}
}
//console.log(`chunk array: ${chunkArr}` );
return chunkArr;
}
// end of _ object
};
const array = [1,2,3,4];
console.log(_.chunk(array, 2));
const array1 = [1,2,3,4,5,6,7,8];
const chunk = (arr, size = 2, sum = []) => {
if (arr.length <= size) {
return sum.concat([arr])
}
return chunk(arr.slice(size), size, sum.concat([arr.slice(0, size)]));
}
console.log(chunk(array1, 5))

Inconsistency, when returning index of duplicate values

I'm trying to create an algorithm to find duplicate values in a list and return their respective indexes, but the script only returns the correct value, when I have 2 equal elements:
array = [1,2,0,5,0]
result -> (2) [2,4]
Like the example below:
array = [0,0,2,7,0];
result -> (6) [0, 1, 0, 1, 0, 4]
The expected result would be [0,1,4]
Current code:
const numbers = [1,2,0,5,0];
const checkATie = avgList => {
let averages, tie, n_loop, currentAverage;
averages = [... avgList];
tie = [];
n_loop = 0;
for(let n = 0; n <= averages.length; n++) {
currentAverage = parseInt(averages.shift());
n_loop++
for(let avg of averages) {
if(avg === currentAverage) {
tie.push(numbers.indexOf(avg),numbers.indexOf(avg,n_loop))
};
};
};
return tie;
}
console.log(checkATie(numbers));
if possible I would like to know some way to make this code more concise and simple
Use a Set
return [...new Set(tie)]
const numbers1 = [1,2,0,5,0];
const numbers2 = [0,0,2,7,0];
const checkATie = avgList => {
let averages, tie, n_loop, currentAverage;
averages = [... avgList];
tie = [];
n_loop = 0;
for(let n = 0; n <= averages.length; n++) {
currentAverage = parseInt(averages.shift());
n_loop++
for(let avg of averages) {
if(avg === currentAverage) {
tie.push(avgList.indexOf(avg),avgList.indexOf(avg,n_loop))
};
};
};
return [...new Set(tie)]
}
console.log(checkATie(numbers1));
console.log(checkATie(numbers2));
I hope this help you.you can use foreach function to check each item of array
var array = [0,0,2,7,0];
var result = [] ;
array.forEach((item , index)=>{
if(array.findIndex((el , i )=> item === el && index !== i ) > -1 ){
result.push(index)
}
})
console.log(result);
//duplicate entries as an object
checkDuplicateEntries = (array) => {
const duplicates = {};
for (let i = 0; i < array.length; i++) {
if (duplicates.hasOwnProperty(array[i])) {
duplicates[array[i]].push(i);
} else if (array.lastIndexOf(array[i]) !== i) {
duplicates[array[i]] = [i];
}
}
console.log(duplicates);
}
checkDuplicateEntries([1,2,0,5,0]);
// hope this will help
Create a lookup object with value and their indexes and then filter all the values which occurred more than once and then merge all indexes and generate a new array.
const array = [1, 2, 0, 5, 0, 1, 0, 2],
result = Object.values(array.reduce((r, v, i) => {
r[v] = r[v] || [];
r[v].push(i);
return r;
}, {}))
.filter((indexes) => indexes.length > 1)
.flatMap(x => x);
console.log(result);

How to pass array values as an object prop dynamicly?

I need to treat array values as props of object. For example:
let arr = ['masa_icerik', 'urunler', 0, 'urun_adet'];
let obj = {
"_id": "5c13bd566704aa5e372dddcf",
"masa_id": 3,
"masa_numara": 3,
"masa_magaza": 1,
"masa_icon": "kola",
"masa_adi": "salon 3",
"masa_durum": 1,
"masa_icerik": {
"adisyon": "J1554745811908",
"urunler": [{
"urun_adet": 14,
"urun_fiyat": 3,
"urun_id": "5c16686b93d7b79ae6367864",
"urun_odenen": 0
}, {
"urun_adet": 1,
"urun_fiyat": 5,
"urun_id": "5c16686b93d7b79ae6367865",
"urun_odenen": 0
}]
},
"masa_acilis": "2019-04-08T17:50:12.052Z",
"masa_acan": "5c1eda01d1f4773110dd6ada"
};
I have an array and an object like above and I want to do something like this:
let res;
arr.forEach(elem => {
res = obj[elem];
});
and after that I need to get something like :
obj['masa_icerik']['urunler'][0]['urun_adet']
The number of the values is dynamic from server. Thats why i need something like this. Is there any way to do that? I need to change that property and return the changed obj.
You can use forEach loop to loop thru the array and store it to a temp variable. If all elements exist, it will change the value.
let arr = ['a', 'b', 'c'];
let obj = {'a':{'b':{'c':1}}};
let newValue = "NEW VALUE";
let temp = obj;
arr.forEach((o, i) => {
if (i < arr.length - 1) temp = temp[o] || null;
else if (temp !== null && typeof temp === "object" ) temp[o] = newValue;
});
console.log(obj);
If there are multiple multiple object properties missing in the last part of the array.
let arr = ['a', 'b', 'c', 'd'];
let obj = {'a': {'b': {}}};
let newValue = "NEW VALUE";
let temp = obj;
arr.forEach((o, i) => {
if (i < arr.length - 1) {
if (!temp[o]) temp[o] = {[arr[i + 1]]: {}};
temp = temp[o];
} else if (temp !== null && typeof temp === "object") temp[o] = newValue;
});
console.log(obj);
You can use references
Here idea is
Initialize val with object reference
Loop through array and keep setting new reference to val
let arr = ['a','b','c'];
let obj = {'a':{'b':{'c':1}}};
let getMeValue = (arr) => {
let val=obj;
arr.forEach(e => val = val && val[e] )
return val
}
console.log(getMeValue(arr))
console.log(getMeValue([1,2,3]))
UPDATE: I want to change values
let arr = ['a','b','c'];
let obj = {'a':{'b':{'c':1}}};
let getMeValue = (arr) => {
let val = obj
arr.forEach((e,i) => {
if(i === arr.length-1 && val){
val[e] = 5
}
else {
val = val && val[e]
}
})
return obj
}
console.log(getMeValue(arr))
I am not fully understanding where you are getting the new values from but I think this will get you on the right track.
let newObj = {};
arr.map(each => {
newObj[each] = "new value";
})
console.log(newObj);
I'm not sure about your requirment here, I guess you want the below:
let func = (arr, value)=>{
r = {};
r[arr[arr.length-1]] = value;
for(let i = arr.length-2; i>=0; i--){
obj = {};
obj[arr[i]] = r;
r = obj;
}
return r;
}
console.log(func(['a', 'b', 'c'], 1));

JavaScript ES6 - count duplicates to an Array of objects

I'm creating for my list of products a filter to count all producers and display like this:
Apple (3)
I eliminated the duplicates from array: ["Apple","Apple","Apple"] I used this link:
Get all non-unique values (i.e.: duplicate/more than one occurrence) in an array
But my problem is that I want to count these elements from array and display them in an Array of Objects cause i need to iterate it later.
From this Array of Apples above i need result: [{"Apple": 3},{...},{...}]
I was trying to do this but it returns me object and I can't iterate after it:
How to count duplicate value in an array in javascript
I need an Array of Objects it's not duplicated
I'm using Angular 4.
My code:
component.ts
async ngOnInit() {
this.cart$ = await this.cartService.getCart();
this.subscription = this.productService.getAll().subscribe(products => {
this.category = products.filter(
products => products.category == this.name
);
this.filters();
});
}
filters() {
this.category2 = this.category.map(value => value.producer);
this.filteredArray = this.eliminateDuplicates(this.category2);
console.log(this.filteredArray);
}
eliminateDuplicates(arr) {
let i,
len = arr.length,
out = [],
obj = {};
for (i = 0; i < len; i++) {
obj[arr[i]] = 0;
}
for (i in obj) {
out.push(i);
}
return out;
}
component.html
<div *ngFor="let f of filteredArray">
{{f}}
</div>
You can use reduce to summarize the array and map for form the desired output
let obj = ["Apple", "Apple", "Apple", "Orange"];
let result = Object.values(obj.reduce((c, v) => {
c[v] = c[v] || [v, 0];
c[v][1]++;
return c;
},{})).map(o=>({[o[0]] : o[1]}));
console.log(result);
Here:
const array = ["a", "a", "b"]
const result = { }
for (let i = 0; i < array.length; i++) {
result[array[i]] = (result[array[i]] || 0) + 1
}
Object.keys(result).map(key => ({ [key]: result[key] }))
That last line is the key for
I was trying to do this but it returns me object
you can simply do it by using Lodash countBy function
filters() {
this.category2 = this.category.map(value => value.producer);
this.filteredArray = _.countBy(this.category2);
console.log(this.filteredArray);
// Object {Apple: 3, Orange: 1}
}
You can simply do it by using array.reduce() method
const votes = ['Yes', 'Yes', 'Yes', 'No', 'No', 'Absent'];
const result = votes.reduce((prevValue, vote) => {
if (prevValue[vote]) {
prevValue[vote]++;
} else {
prevValue[vote] = 1;
}
return prevValue;
}, {});
console.log(result);
Output : { Yes: 3, No: 2, Absent: 1 }

Array of objects with key/value pairs from given arrays of keys & values

I am trying to return an array of key-value pairs: [{"a": 1},{"b": 2},{"c": 3}] from a given array of keys: ["a", "b", "c"] and an array of values: [1, 2, 3]
I have tried this:
let arr = [], obj = {}, key, val;
const keyValuePairs = (k, v) => {
if (k.length === v.length) {
for (var i = 0; i < k.length; i++) {
key = k[i]; val = v[i];
arr[i] = {key: val};
}
} return arr;
};
keyValuePairs(["a", "b", "c"], [1, 2, 3]);
But it's returning - [ { key: 1 }, { key: 2 }, { key: 3 } ]
How can I do it?
If you're targeting a new enough browser, or are using babel, there is a new syntax that allows this easily:
arr[i] = {[key]: val};
Otherwise you will need to use multiple lines to set the key
let arr = [], obj = {}, key, val;
const keyValuePairs = (k, v) => {
if (k.length === v.length) {
for (var i = 0; i < k.length; i++) {
key = k[i]; val = v[i];
var newObj = {};
newObj[key] = val;
arr[i] = newObj;
}
} return arr;
};
Just general code comments: You have a bunch of variables out of the scope of the function. It's also quite verbose. You can write the entire function like this:
const keyValuePairs = (k, v) => (
k.map((key, index) => ({ [key]: v[index] }))
);
a = ["a", "b", "c"], b = [1, 2, 3]
c = a.map((k, i) => ({[k]: b[i]}))
console.log(JSON.stringify(c))
How do I zip two arrays in JavaScript?
Try this(simple solution):
var answer = keyValuePairs(["a", "b", "c"], [1, 2, 3]);
console.log(answer);
function keyValuePairs(arrOne, arrTwo){
var returnArr = [];
for(var i = 0; i < arrOne.length; i++){
var obj = {};
obj[arrOne[i]] = arrTwo[i];
returnArr[i] = obj;
}
return returnArr;
}
using lodash you can do this in one line with _.map or the vanilla Array.prototype.map and using the index i to stripe across the arrays.
var keys = 'abc'.split('');
var values = '123'.split('');
var result = _.map(keys, (key, i) => ( { [keys[i]] : values[i] } ) );
console.log(JSON.stringify(result));
yields:
[{"a":"1"},{"b":"2"},{"c":"3"}]
you can also continue this pattern dimensionally:
var keys = 'abc'.split('');
var values = '123'.split('');
var valuesValues = 'xyz'.split('');
var result = _.map(keys, (key, i) => ( { [keys[i]] : { [ values[i] ]: valuesValues[i] } } ) );
console.log(JSON.stringify(result));
yields:
[{"a":{"1":"x"}},{"b":{"2":"y"}},{"c":{"3":"z"}}]
you can use reduce method also as per your requirement.
see below example..
let keys = ["a", "b", "c"],
values = [1, 2, 3],
result = keys.reduce((r,v,i)=>r.concat({[v]:values[i]}),[]);
console.log(result);;

Categories