How to convert array to array of objects? - javascript

I have
let array = ['mango', 'mango_shake','banana', 'banana_shake', 'cherry', 'cherry_shake', 'Strawberry', 'Strawberry_shake', ...n];
What i want to do is:
let target = [{'fruit': 'mango', 'drink': 'mango_shake'},
{'fruit': 'banana', 'drink': 'banana_shake'}, ...n];
How can i do it?

You can simply loop through array and create an array of object like this
let array = ['mango', 'mango_shake', 'banana', 'banana_shake', 'cherry', 'cherry_shake', 'Strawberry', 'Strawberry_shake'];
var res = [];
for (var i = 0; i < array.length; i = i + 2) {
var ob = {};
ob.fruit = array[i];
ob.drink = array[i + 1];
res.push(ob);
}
console.log(res);
Note: This answer assumes the fruit and its corresponding drink are always right beside each other in the array. This will give wrong answers if items are out of order.

Just iterate over your original array until it is empty and take out pairs and map them to objects:
const result = [];
while(array.length)
result.push((([fruit, drink]) => ({fruit, drink}))(array.splice(0, 2));
(In case this is your homework: i think it will be harder to explain to your teacher how it works instead of just trying it on your own :))

You can iterate over the array to combine every other item
let target = {};
array.forEach( (curr, indx, arr) => {
if (indx %2 == 1) {
target[arr[indx-1]] = curr
}
});

Related

Why i can't remove other array element in javascript?

I am working with arrays now but if I remove the second element that I choose the first one that I removed keeps returning to its spot. How can I solve this?
Here is the Code:
const fruits = ['Apple', 'Banana','Lemon', 'Guava'];
const removeItem = (arr, item) => {
let newArray = [...arr];
const index = newArray.findIndex((element)=>element===item)
if(index !== -1){
newArray.splice(index, 1)
return newArray
}
}
console.log(removeItem(fruits, 'Guava'))
console.log(removeItem(fruits, 'Lemon'))
Output:
(3) ['Apple', 'Banana', 'Lemon'] //I removed Guava
(3) ['Apple', 'Banana', 'Guava'] //I removed Lemon
Your original array is a const and cannot be updated. So it is using all original values. Here is a working version that removes from the original array.
let fruits = ['Apple', 'Banana','Lemon', 'Guava'];
const removeItem = (arr, item) => {
let newArray = [...arr];
const index = newArray.findIndex((element)=>element===item)
if(index !== -1){
newArray.splice(index, 1)
fruits = newArray;
return newArray
}
}
console.log(removeItem(fruits, 'Guava'))
console.log(removeItem(fruits, 'Lemon'))
Keywords to think about: pop push remove index placeholder
I don't understand what you are trying to achieve.
Well, I never tried Guava.

Algorithm Challenge: Fuzzy Search

I recently took part in an algorithm challenge to create a Fuzzy search with the following criteria:
Given a set array, create a function that receives one argument and returns a new array containing only the values that start with either:
A) The argument provided
B) The argument provided but with 1 difference (i.e. 1 incorrect letter)
The array was: fruits = [apple, apricot, banana, pear, mango, cherry, tomato]
so:
fuzzySearch('ap') = ['apple, apricot']
fuzzySearch('app') = ['apple', 'apricot']
fuzzySearch('appl') = ['apple']
fuzzySearch('pa') = ['banana', 'mango']
This is the solution I came up with:
const fruits = ['apple', 'apricot', 'banana', 'pear', 'mango', 'cherry', 'tomato']
function fuzzySearch(str) {
return fruits.filter(fruit =>
{
let letterCount = 0
const fruitLetArr = fruit.toLowerCase().split('')
const strArr = str.toLowerCase().split('')
for (var i = 0; i < strArr.length; i++) {
console.log(fruitLetArr[i], strArr[i], i, letterCount)
if (fruitLetArr[i] !== strArr[i]) letterCount++
if (letterCount === 2) break;
}
if (letterCount < 2) return true
});
}
fuzzySearch(str)
Can anyone think of a faster way that doesn't involve iterating over every value before a soltion can be found?
Here's something that should be slightly more efficient. Also easier to read. In this solution, I am assuming that by "difference" you mean a substitution of a letter for another letter, rather than the addition of another letter.
const fruits = ['apple', 'apricot', 'banana', 'pear', 'mango', 'cherry', 'tomato'];
const fuzzySearch = (str) => {
return fruits.filter((fruit) => {
// If our first case is met, immediately return
if (fruit.startsWith(str)) return true;
// Split the fruit based on the length of input string
const test = fruit.slice(0, str.length).split('');
let diffs = 0;
// Compare + keep track of differences between input + sliced fruit
test.forEach((letter, i) => letter !== str[i] && diffs++);
// If we have more than one difference, it doesn't meet case #2
if (diffs > 1) return false;
return true;
});
};
const testCases = ['ap', 'app', 'appl', 'pan', 'bp'];
for (const testCase of testCases) {
console.log(fuzzySearch(testCase));
}

Extracting intersection between two javascript arrays [duplicate]

This question already has answers here:
Simplest code for array intersection in javascript
(40 answers)
Closed 3 years ago.
I have two arrays, and I want to be able to compare the two and only return the values that match. For example both arrays have the value cat so that is what will be returned. I haven't found anything like this. What would be the best way to return similarities?
var array1 = ["cat", "sum","fun", "run"];
var array2 = ["bat", "cat","dog","sun", "hut", "gut"];
//if value in array1 is equal to value in array2 then return match: cat
You can use :
const intersection = array1.filter(element => array2.includes(element));
Naturally, my approach was to loop through the first array once and check the index of each value in the second array. If the index is > -1, then push it onto the returned array.
​Array.prototype.diff = function(arr2) {
var ret = [];
for(var i in this) {
if(arr2.indexOf(this[i]) > -1){
ret.push(this[i]);
}
}
return ret;
};
​
My solution doesn't use two loops like others do so it may run a bit faster. If you want to avoid using for..in, you can sort both arrays first to reindex all their values:
Array.prototype.diff = function(arr2) {
var ret = [];
this.sort();
arr2.sort();
for(var i = 0; i < this.length; i += 1) {
if(arr2.indexOf(this[i]) > -1){
ret.push(this[i]);
}
}
return ret;
};
Usage would look like:
var array1 = ["cat", "sum","fun", "run", "hut"];
var array2 = ["bat", "cat","dog","sun", "hut", "gut"];
console.log(array1.diff(array2));
If you have an issue/problem with extending the Array prototype, you could easily change this to a function.
var diff = function(arr, arr2) {
And you'd change anywhere where the func originally said this to arr2.
I found a slight alteration on what #jota3 suggested worked perfectly for me.
var intersections = array1.filter(e => array2.indexOf(e) !== -1);
Hope this helps!
This function runs in O(n log(n) + m log(m)) compared to O(n*m) (as seen in the other solutions with loops/indexOf) which can be useful if you are dealing with lots of values.
However, because neither "a" > 1 nor "a" < 1, this only works for elements of the same type.
function intersect_arrays(a, b) {
var sorted_a = a.concat().sort();
var sorted_b = b.concat().sort();
var common = [];
var a_i = 0;
var b_i = 0;
while (a_i < a.length
&& b_i < b.length)
{
if (sorted_a[a_i] === sorted_b[b_i]) {
common.push(sorted_a[a_i]);
a_i++;
b_i++;
}
else if(sorted_a[a_i] < sorted_b[b_i]) {
a_i++;
}
else {
b_i++;
}
}
return common;
}
Example:
var array1 = ["cat", "sum", "fun", "hut"], //modified for additional match
array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
intersect_arrays(array1, array2);
>> ["cat", "hut"]
Loop through the second array each time you iterate over an element in the first array, then check for matches.
var array1 = ["cat", "sum", "fun", "run"],
array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
function getMatch(a, b) {
var matches = [];
for ( var i = 0; i < a.length; i++ ) {
for ( var e = 0; e < b.length; e++ ) {
if ( a[i] === b[e] ) matches.push( a[i] );
}
}
return matches;
}
getMatch(array1, array2); // ["cat"]
var array1 = [1, 2, 3, 4, 5, 6];
var array2 = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var array3 = array2.filter(function(obj) {
return array1.indexOf(obj) !== -1;
});
You can use javascript function .find()
As it says in MDN, it will return the first value that is true. If such an element is found, find immediately returns the value of that element. Otherwise, find returns undefined.
var array1 = ["cat", "sum", "fun", "run", "cat"];
var array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
found = array1.find((val, index) => {
console.log('index', index) // Stops at 0
return array2.includes(val)
})
console.log(found)
Or use .filter(), which loops through every elements first, then give back the result to you.
var array1 = ["cat", "sum", "fun", "run", "cat"];
var array2 = ["bat", "cat", "dog", "sun", "hut", "gut"];
found = array1.filter((val, index) => {
console.log('index', index) // Stops at array1.length - 1
return array2.includes(val)
})
console.log(found)
use lodash
GLOBAL.utils = require('lodash')
var arr1 = ['first' , 'second'];
var arr2 = ['second '];
var result = utils.difference(arr1 , arr2);
console.log ( "result :" + result );
Libraries like underscore and lodash have a utility method called intersection to find matches in arrays passed in. Take a look at: http://underscorejs.org/#intersection
Done as a answer so I can do formatting...
This is the the process you need to go through. Looping through an array for the specifics.
create an empty array
loop through array1, element by element. {
loop through array2, element by element {
if array1.element == array2.element {
add to your new array
}
}
}
If your values are non-null strings or numbers, you can use an object as a dictionary:
var map = {}, result = [], i;
for (i = 0; i < array1.length; ++i) {
map[array1[i]] = 1;
}
for (i = 0; i < array2.length; ++i) {
if (map[array2[i]] === 1) {
result.push(array2[i]);
// avoid returning a value twice if it appears twice in array 2
map[array2[i]] = 0;
}
}
return result;
With some ES6:
let sortedArray = [];
firstArr.map((first) => {
sortedArray[defaultArray.findIndex(def => def === first)] = first;
});
sortedArray = sortedArray.filter(v => v);
This snippet also sorts the firstArr based on the order of the defaultArray
like:
let firstArr = ['apple', 'kiwi', 'banana'];
let defaultArray = ['kiwi', 'apple', 'pear'];
...
console.log(sortedArray);
// ['kiwi', 'apple'];
Iterate on array1 and find the indexof element present in array2.
var array1 = ["cat", "sum","fun", "run"];
var array2 = ["bat", "cat","sun", "hut", "gut"];
var str='';
for(var i=0;i<array1.length;i++){
if(array2.indexOf(array1[i]) != -1){
str+=array1[i]+' ';
};
}
console.log(str)

Dedup array and sort array by most frequent occurrence (with LoDash)

Say I have an array that goes something like:
fruit_basket = ['apple', 'orange', 'banana', 'pear', 'banana']
I want to make an array fruits that consists of the fruits found in fruit basket, sorted in order of most frequently occurring fruit. (If there are ties I don't care about ordering.)
So one valid value for fruits is:
['banana', 'orange', 'apple', 'pear']
What's the most concise way to achieve this using LoDash? I don't care about run time performance.
First you'd count the occurences
var x = _.chain(fruit_basket).countBy(); // {apple: 1, orange: 1, banana: 2, pear: 1}
Then you'd pair them and sort by the number of occurences, using reverse to get the largest number first
var y = x.toPairs().sortBy(1).reverse(); //[["banana",2],["pear",1],["orange",1],["apple",1]]
Then you'd just map back the keys, and get the value as an array
var arr = y.map(0).value(); // ['banana', 'orange', 'apple', 'pear']
All chained together, it looks like
var arr = _.chain(fruit_basket).countBy().toPairs().sortBy(1).reverse().map(0).value();
Without loDash, something like this would do it
var fruit_basket = ['apple', 'orange', 'banana', 'pear', 'banana'];
var o = {};
fruit_basket.forEach(function(item) {
item in o ? o[item] += 1 : o[item] = 1;
});
var arr = Object.keys(o).sort(function(a, b) {
return o[a] < o[b];
});
Here's my take on this.
It doesn't use lodash as the question asks for. It's a vanilla alternative. I feel this could be valuable to people who land here from Google and don't want to use lodash (that's how I got here, at least).
const orderByCountAndDedupe = arr => {
const counts = new Map();
arr.forEach( item => {
if ( !counts.has(item) ) {
counts.set(item, 1);
} else {
counts.set(item, counts.get(item)+1);
}
});
return (
Array.from(counts)
.sort( (a, b) => b[1] - a[1])
.map( ([originalItem, count]) => originalItem)
);
};
An approach using for loop Array.prototype.splice()
var fruit_basket = ['apple', 'orange', 'banana', 'pear', 'banana'];
var res = [];
for (var i = 0; i < fruit_basket.length; i++) {
var index = res.indexOf(fruit_basket[i]);
// if current item does not exist in `res`
// push current item to `res`
if (index == -1) {
res.push(fruit_basket[i])
} else {
// else remove current item , set current item at index `0` of `res`
res.splice(index, 1);
res.splice(0, 0, fruit_basket[i])
}
}
console.log(res)
You can count occurences using _.countBy and then use it in _.sortBy:
var counter = _.countBy(fruit_basket)
var result = _(fruit_basket).uniq().sortBy(fruit => counter[fruit]).reverse().value()

Word Frequency Count, fix a bug with standard property

I'm trying to build a javascript function which would count the number of occurrences of each word in an input array.
Example :
Input
a=["a","booster","booster","constructor","adam","adam","adam","adam"]
Output:
"a":1
"booster":2
"constructor":1
"adam":4
Output should be dict-alike.
I'm new to javascript and I tried to use a dict. But objects have a property called "constructor", so cnt["constructor"] seems not to work.
Here is my code and the result:
var cnt={};
console.log("constructor");
for(var i=0;i<a.length;++i)
{
if(! (a[i] in cnt))
cnt[a[i]]=0;
else
cnt[a[i]]+=1;
}
for(var item in cnt)
console.log(item+":"+cnt[item]);
Result:
You can see that 1 is added to constructor of cnt as a string.
function count(arr){
return arr.reduce(function(m,e){
m[e] = (+m[e]||0)+1; return m
},{});
}
The idea behind are
the use of reduce for elegance
the conversion of m[e] to a number using +m[e] to avoid the constructor (or toString) problem
Demonstration
var arr = ['apple', 'orange', 'grape', 'apple'];
var initialValue = {};
var result = arr.reduce(function(accumulator, curr, idx, arr) {
if (Object.hasOwnProperty.call(accumulator, curr)) { // does current exist as key on initialValue object?
accumulator[curr]++;
} else { // no key for current on initialValue object
accumulator[curr] = 1;
}
return accumulator;
}, initialValue);
console.log(result);
You can also create an array just by initializing [] as the initial accumulator.
var fruits = ['apple', 'orange', 'grape', 'apple'].reduce((countFruits,currentFruit)=>{
if(typeof countFruits[currentFruit]!=="undefined"){
countFruits[currentFruit] = countFruits[currentFruit]+1
return countFruits
}
countFruits[currentFruit] = 1
return countFruits
},[])
console.log(fruits)

Categories