Related
I have an array and what I want to do with this if to check if all the elements has the same magnitude for example:
array [40, 20, 30, 10] has 10 as magnitude so output should be true
array [1, 2, 3, 1, 2, 3] has 1 as magnitude so output should be true
array [2, 6, 12, 20] has more than one magnitude so output should be false
The could should be work with integers and floats, incluiding negative numbers.
What I tried is to use some code from here but seems that this only works for consecutive numbers and if there are repeated x times. So I wonder if this code can be addapted to fix my problem or if there is another way to solve it.
Code:
function consecutive(array) {
var i = 2, d;
while (i < array.length) {
d = array[i - 1] - array[i - 2];
if (Math.abs(d) === 1 && d === array[i] - array[i - 1]) {
return false;
}
i++;
}
return true;
}
var array = [3, 2, 1, 2, 3, 4, 3]; // Return true
// var array = [194, 54, 23, 7, 3, 6, 8 ] //Example 2 Return false
console.log(consecutive(array));
I guess this should do the trick...
// array [40, 20, 30, 10] has 10 as magnitude so output should be true
// array [1, 2, 3, 1, 2, 3] has 1 as magnitude so output should be true
// array [2, 6, 12, 20] has more than one magnitude so output should be false
const arr1 = [40, 20, 30, 10];
const arr2 = [1, 2, 3, 1, 2, 3];
const arr3 = [2, 6, 12, 20];
const magnitude = items => {
const unique = [...new Set(items)];
const sorted = unique.sort((a,b) => a-b);
const mags = [];
sorted.forEach((item, idx) => {
if (idx + 1 >= sorted.length) return null;
const next = sorted[idx + 1];
mags.push(item - next);
});
return [...new Set(mags)].length <= 1;
};
console.log('arr1', magnitude(arr1));
console.log('arr2', magnitude(arr2));
console.log('arr3', magnitude(arr3));
You can try like below
const arr1 = [40.10, 20.10, 30.10, 10.10, 50.20];
const arr2 = [40.10, 20.10, 30.10, 10.10, 50.10];
const arr3 = [40, 20, 30, 10, 50];
const hasSameMagnitue = (values: number[]): boolean => {
const sortByOrder = values.sort();
const diff = sortByOrder.slice(0, -1).map((el, index) => (sortByOrder[index + 1] - el).toFixed(2));
const result = diff.every((el) => el === diff[0]);
return result;
}
console.log('hasSameMagnitue', hasSameMagnitue(arr1)); // false
console.log('hasSameMagnitue', hasSameMagnitue(arr2)); // true
console.log('hasSameMagnitue', hasSameMagnitue(arr3)); // true
I have an array,
const arr = [1, 2, 3, 4, 5, 6];
let us say I give it a condition to return numbers above 3, using the .filter() method, returns a new array.
But I need it to return the original array but making the array values that do not meet the conditions empty.
The new array should be
[ , , , , 4, 5, 6 ]
Is this possible?
Edit
Here are the changed requirements.
I have an array,
const arr = [
{ myNumber: 1, name: 'one' },
{ myNumber: 3, name: 'tree' },
{ myNumber: 6, name: 'six' },
{ myNumber: 8, name: 'eight' }
];
let us say I give it a condition to return names that include alphabet I, using the .filter() method, returns a new array.
But I need it to return the original array but making the array values that do not meet the conditions empty
The new array should be
const arr = [
{ myNumber: '', name: '' },
{ myNumber: '', name: '' },
{ myNumber: 6, name: 'six' },
{ myNumber: 8, name: 'eight' }
];
Is this possible?
To map value and modify existing array use forEach method and modify element of array.
const arr = [1, 2, 3, 4, 5, 6];
arr.forEach((ele, idx) => {
if(ele <= 3) arr[idx] = null;
});
console.log(arr);
You could delete unwanted items.
const
array = [1, 2, 3, 4, 5, 6];
for (let i = 0; i < array.length; i++) if (array[i] <= 3) delete array[i];
console.log(array);
array.forEach((v, i) => console.log(v, i));
.as-console-wrapper { max-height: 100% !important; top: 0; }
[ , , , , 4, 5, 6 ] is not possible. However, [ undefined, undefined, undefined, undefined, 4, 5, 6 ] is possible, as well as [ null, null, null, null, 4, 5, 6 ].
So, instead of using .filter(), I would use map() :
const arr = [1, 2, 3, 4, 5, 6];
const newArr = arr.map((x) => x <= 3 ? undefined : x);
console.log(newArr);
If you want the changes to be made in place, use the same logic, but in a regular loop :
const arr = [1, 2, 3, 4, 5, 6];
arr.forEach((element, index, original) => {
if (element <= 3)
original[index] = undefined;
});
console.log(arr);
This new answer is going to prove that even with entirely changed requirements a generic idea (a generic base approach) can be adapted easily to the changes but still can be recognized.
With the new requirements one does not need to change the original array itself but each item (reference) of it. Thus forEach will be the new array method of choice.
The reduce and condition based answer of the former requirements provides the main idea of working with customizable functions for e.g condition and, newly introduced with this approach, the item specific mutation via resetValues ...
function resetConditionMatchingItemValuesViaBoundConfig(item) {
const { condition, resetValues } = this; // `this` equals bound `config`.
if (condition(item)) {
// mutate an original array's item.
resetValues(item);
}
}
function isItemNumberValueLowerEqualThanThree(item) {
return (item.myNumber <= 3);
}
function resetItemValues(item) {
item.myNumber = Number.NaN;
//item.myNumber = '';
item.name = '';
}
const arr = [
{ myNumber: 1, name: 'one' },
{ myNumber: 3, name: 'tree' },
{ myNumber: 6, name: 'six' },
{ myNumber: 8, name: 'eight' }
];
console.log('before mutation ... arr :', arr);
arr.forEach(resetConditionMatchingItemValuesViaBoundConfig, {
condition: isItemNumberValueLowerEqualThanThree,
resetValues: resetItemValues,
});
console.log('after mutation ... arr :', arr);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Since the OP was asking for an array method I, as so often, want to promote Array.prototype.reduce. It proves itself to be an elegant swiss-knife again and again, ... but see yourself ...
function deleteConditionMatchingItem(condition, item, idx, arr) {
if (condition(item)) {
// mutate the original array.
delete arr[idx];
}
return condition;
}
function isLowerEqualThanThree(value) {
return (value <= 3);
}
const arr = [1, 2, 3, 4, 5, 6];
console.log('before mutation ... arr :', arr);
arr.reduce(deleteConditionMatchingItem, isLowerEqualThanThree);
console.log('after mutation ... arr :', arr);
console.log('("0" in arr ) ? ', ("0" in arr ));
console.log('("1" in arr ) ? ', ("1" in arr ));
console.log('("2" in arr ) ? ', ("2" in arr ));
console.log('("3" in arr ) ? ', ("3" in arr ));
console.log('("4" in arr ) ? ', ("4" in arr ));
console.log('("5" in arr ) ? ', ("5" in arr ));
console.log('("6" in arr ) ? ', ("6" in arr ));
.as-console-wrapper { min-height: 100%!important; top: 0; }
I want to convert the below JSON format
let init = {
test1: [1, 2, 3, 4, 5],
test2: [6, 7, 8, 9, 10]
}
into this format using javascript native methods of array or object (supported in all browsers)
[{
test1: 1,
test2: 6
},{
test1: 2,
test2: 7
},{
test1: 3,
test2: 8
},{
test1: 4,
test2: 9
},{
test1: 5,
test2: 10
}]
I have tried with for loop and below is the code,
let keys = Object.keys(init);
let result = [];
for(let i = 0; i < keys.length; i++){
let key = keys[i];
for(let j = 0; j < init[key].length; j++){
if(i === 0){
let obj1 = {};
obj1[key] = init[key][j];
result.push(obj1);
}else{
let obj2 = result[j];
obj2[key] = init[key][j];
}
}
}
You could use Array.prototype.reduce() to do that.
Iterate on test1 array elements and push a new object to the array accumulator with test1 and test2 properties and their respective values.
let init = {
test1: [1, 2, 3, 4, 5],
test2: [6, 7, 8, 9, 10]
};
let keys = Object.keys(init);
let key1 = keys[0];
let key2 = keys[1];
let result = init[key1].reduce((acc, curr, i) => {
acc.push({
[key1]: curr,
[key2]: init[key2][i]
});
return acc;
}, []);
console.log(result);
As of now, reduce() method is supported in most of the modern browsers. For supporting all browsers, it is better to use for loop, but instead of Object.keys() iterate on object properties or use a polyfill.
let init = {
test1: [1, 2, 3, 4, 5],
test2: [6, 7, 8, 9, 10]
};
let keys = [];
for (let key in init) {
if (init.hasOwnProperty(key)) {
keys.push(key);
}
}
let key1 = keys[0];
let key2 = keys[1];
let result = [];
for (let i = 0; i < key1.length; i++) {
result.push({
[key1]: init[key1][i],
[key2]: init[key2][i]
});
}
console.log(result);
You could use a combination of for...in and Array.forEach to achieve this result in a few lines of code. If you wan't support for all browsers you can better use var instead of let though. https://caniuse.com/#search=let
var init = {
test1: [1, 2, 3, 4, 5],
test2: [6, 7, 8, 9, 10]
}
var result = []
for (var key in init) {
init[key].forEach(function (item, index) {
result[index] ? result[index][key] = item : result[index] = { [key]: item }
})
}
console.log(result)
You could maybe simplify this a bit more by initializing your result with empty objects, that would avoid using a ternary statement. That would look like this:
Disclaimer: This won't work in IE11 because of the lack of Array.fill() support
var init = {
test1: [1, 2, 3, 4, 5],
test2: [6, 7, 8, 9, 10]
}
var result = new Array(Object.keys(init)[0].length).fill().map(Object);
for (var key in init) {
init[key].forEach(function(item, index) {
result[index][key] = item
})
}
console.log(result)
If you do this make sure you don't create an array with Objects that are a reference to the same object in memory: Array.prototype.fill() with object passes reference and not new instance
I have an array with numbers. I would like to put the numbers in order and create new array with duplicats in the same array(array in array). Can someone please help me step by step. I would really like to understand
let arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
// I want to create this [[1,1,1,1],[2,2,2], 4,5,10,[20,20], 391, 392,591]
const sortArray = arr.sort(function(a, b) {
return a - b;
});
You can extract unique values using Set, then sort them (because sorting an array of arrays is more complex), then use array.reduce to acquire all the items in the original array and push either the single value if unique, otherwise the array of values (not sure why you need that, but still..)
Further documentation reference:
What is Set?
Array.reduce
Working code below:
let arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
// I want to create this [[1,1,1,1],[2,2,2], 4,5,10,[20,20], 391, 392,591]
console.log([...new Set(arr)].sort((a,b) => a - b).reduce((accumulator, next) => {
const filtered = arr.filter(i => i === next);
return accumulator.push(filtered.length === 1 ? filtered[0] : filtered), accumulator
}, []));
You could sort the array and have a look to the last two items and the actual item.
[ 1, 1, 1, 1, 2, 2, 2, 4, 5, 10, 20, 20, 391, 392, 591] array
a b c variables
^ actual item
Then check if the last item b and the actual item c is unequal and return a new array with the the old items and the actual item.
If the item before the last item a and the actual item is unequal, it should be an array for the last item in the result set and the actual item.
Otherwise push the actual item to the nested last array of the result set.
var array = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20],
result = array
.sort((a, b) => a - b)
.reduce((r, c, i, { [i - 2]: a, [i - 1]: b }) => {
if (b !== c) return [...r, c];
if (a !== c) return r.pop(), [...r, [b, c]];
r[r.length - 1].push(c);
return r;
}, []);
console.log(result);
Although there are other approaches, whenever I need to parse unique values from an array in this way, I will create an object with the object's properties representing the groupings of array values
{ 1: [1, 1, 1], 2: [2 , 2, 2], 4: [4], 5: [5] ...}
Then you can use a native object method to get all keys or values from the object if you need to (or if your end goal is different, you can use the object however it is needed)
Object.keys(obj)
// or
Object.values(obj)
For your case, it would look like
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const obj = arr.reduce((accum, val) => {
accum[val] = accum[val] || [];
accum[val].push(val);
return accum;
}, {});
const finalArr = Object.values(obj).map(val => val.length > 1 ? val : val[0]);
console.log(finalArr);
You can count the occurrences and then use that object to create your final array.
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const count = arr.reduce((acc, val) => {
acc[val] = acc[val] + 1 || 1;
return acc;
}, {});
const result = Object
.keys(count)
.sort((a, b) => a - b)
.map((key) => count[key] === 1 ? +key : Array.from({ length: count[key] }).fill(+key));
console.log(result);
You can do this thing in ways. But if you want to achieve in best way, you must avoid n square loops.
So can create a dictionary of count of values. And loop over the keys of the object in sorted order.
Using Array.reduce to create object of count of array elemnts. and Array.fill to fil an array with same values.
//Given Array
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
//Dictionary with count of each values in array
const arrCountObj = arr.reduce((acc, el) => {
if (acc[el]) {
acc[el] += 1
} else {
acc[el] = 1
}
return acc
}, {})
console.log(arrCountObj)
//Looping over sorted dictionary keys to create array based on condition
var out = Object.keys(arrCountObj).sort((a, b) => a - b).map(x => arrCountObj[x] > 1 ? new Array(arrCountObj[x]).fill(+x) : arrCountObj[x])
console.log(out)
Time Complexity: O(nlogn)
You could:
1) iterate through the array an build a frequency map of the the numbers
2) grab and sort the frequency map key in ascending order
3) build a new array from the information in the frequency map
const arr = [1, 2, 4, 591, 392, 391, 2, 5, 10, 2, 1, 1, 1, 20, 20];
const obj = arr.reduce((acc, c) => {
return acc[c] = (acc[c] || 0) + 1, acc;
}, {});
// {"1":4,"2":3,"4":1,"5":1,"10":1,"20":2,"391":1,"392":1,"591":1}
const keys = Object.keys(obj).sort((a, b) => a - b).map(Number);
// [1,2,4,5,10,20,391,392,591]
const out = keys.map((key) => {
return obj[key] > 1 ? Array(obj[key]).fill(key) : key;
});
// [[1,1,1,1],[2,2,2],4,5,10,[20,20],391,392,591]
console.log(JSON.stringify(out));
You can use reduce and then Array.fill. Here the reduce will create an object like this
{
"1": 4,
"2": 3,
"4": 1,
"5": 1,
"10": 1,
"20": 2,
"391": 1,
"392": 1,
"591": 1
}
which mean there are 4 1s, 3 2s and so on. Then you can use array fill after iterating this object. The array fill syntax is arr.fill(value[, start[, end]])
So in our case we will case new Array(k[keys]).fill(+keys, 0, k[keys]) is creating a new array of length 4,3 so on except for 1 and from 0th index it is filling with the key
let arr = [1, 2, 4, 591, 392, 391,1, 2, 5, 10, 2, 1, 1, 1, 20, 20];
let k = arr.reduce(function(acc, curr) {
if (curr in acc) {
acc[curr] += 1;
} else {
acc[curr] = 1
}
return acc;
}, {});
let grouped = [];
for (let keys in k) {
if (k[keys] !== 1) {
grouped.push(new Array(k[keys]).fill(+keys, 0))
} else {
grouped.push(+keys)
}
}
console.log(grouped)
var foo = { "a": [1,2,3] }
var bar = { "b": [7,8,9] }
output should look like this
[ {a: 1, b: 7}, {a: 2, b: 8}, {a:3, b: 9}]
How can I do this using ramda or javascript functional programming ?
I have done this using for loop i = 0, is it possible using functional ramda programming
If both arrays are always the same length, you can do this using map.
function mergeArrays(arr1, arr2) {
return arr1.map(function(item, index) {
return {
a: arr1[index], //or simply, item
b: arr2[index]
};
});
}
var a = [1, 2, 3];
var b = [7, 8, 9];
var joined = mergeArrays(a, b);
document.getElementById('result').innerHTML = JSON.stringify(joined, null, 2);
<pre id="result">
</pre>
You can achieve this using R.transpose to convert an array of [[1,2,3], [7,8,9]] to [[1, 7], [2, 8], [3, 9]] and then map over it with R.zipObj.
const fn = R.compose(
R.map(R.zipObj(["a", "b"])),
R.transpose
)
const a = [1, 2, 3], b = [7, 8, 9]
const result = fn([a, b])
console.log(result)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
If you would prefer to pass a and b as two arguments to fn rather than an array then you can swap R.transpose in the example above with R.unapply(R.transpose).
Assuming you want [{a:1,b:7},{a:2,b:8},{a:3,b:9}] it can be done pretty easily with map using the index to get the value in b:
var result = a.map((v, i) =>({ a: v, b: b[i] }));
i am having an array
const peopleObject = { "123": { id: 123, name: "dave", age: 23 },
"456": { id: 456, name: "chris", age: 23 }, "789": { id: 789, name:
"bob", age: 23 }, "101": { id: 101, name: "tom", age: 23 }, "102":
{ id: 102, name: "tim", age: 23 } }
for this particular i have created a code that convrts array to object i hope this is usefull for you
const arrayToObject = (array) =>
array.reduce((obj, item) => {
obj[item.id] = item
return obj
}, {})
const peopleObject = arrayToObject(peopleArray)
console.log(peopleObject[idToSelect])
Your expected output doesn't have a valid format. You should store the data in array. Like ,
var output = [];
var a = [1,2,3], b = [7,8,9];
for(var i=0; i< a.length; i++){
var temp = {};
temp['a'] = a[i];
temp['b'] = b[i];
output.push(temp);
}
You cannot store the result in an object the way you want. Objects are key-value pairs. But what you expect is only the values without keys which is not possible!
create function form ramda's addIndex and map
const data = { keys: ['a', 'b', 'c'], values: ['11', '22', '33'] }
const mapIndexed = R.addIndex(R.map)
const result = mapIndexed((item, i) => {
return { [item]: data.values[i] }
}, data.keys)
You will get an array of objects