2 Arrays in JSON - javascript

I'd like to concat 2 arrays in JSON with key and value.
MyArray1 [ "Orange:10", "Orange:5", "Banana:20", "Apple:5" ]
MyArray2 [ "Orange:5", "Banana:10", "Apple:15" ]
MyJSON [
{"fruit": "Orange", "value": 15},
{"fruit": "Banana", "value": 20},
{"fruit": "Apple ", "value": 5},
],[
{"fruit": "Orange", "value": 5},
{"fruit": "Banana", "value": 10},
{"fruit": "Apple ", "value": 15},
]
]
I've tried this but I need a key and value and concat my 2 arrays :
MyArray1.forEach(function(val) {
var item = val.split(":");
var key = item[0];
var num = parseInt(item[1], 10);
if (MyArray1.hasOwnProperty(key)) {
MyArray1[key] += num;
} else {
MyArray1[key] = num;
}
});

As promised, here is a new version that sums up the values of the the same fruit Note that the values are integer which is more convenient for adding. Anyway if you absolutely want strings use arr[i].value=arr[i].value.toString() ;
Please give me a feedback.
var myArray1 = [ "Orange:10", "Orange:5", "Banana:20", "Apple:5" ];
var myArray2 = [ "Orange:5", "Banana:10", "Apple:15" ];
var myObjectArray1 = arrayToObjectArray(myArray1);
var myObjectArray2 = arrayToObjectArray(myArray2);
var myOnlyOneObjectArray= myObjectArray1.concat(myObjectArray2);
var myResult = mergeObjectArray(myOnlyOneObjectArray,"fruit","value")
console.log(myResult);
function arrayToObjectArray(arr){
// Map allows us to return a transformed row for each array row
var arr2 = arr.map(function(item) {
var items = item.split(":");
item = {};
item.fruit = items[0];
item.value = parseInt(items[1]);
return item;
});
return arr2;
}
function mergeObjectArray(arr,compareKey,addKey){
// Pay attention : we loop thru the same arr searching from end to start (i)
// and check if the same fruit already exist (second loop j from start to one row before i)
// that way we can sum any number of concated arrays and even dupes in the same original array
for(var i = arr.length-1; i >=0;i--){
for(var j = 0; j < arr.length -1;j++){ // Note that an objet property can be accessed also this way arr[i]["fruit"] == arr[i].fruit == arr[i][compareKey]
if((arr[i][compareKey]==arr[j][compareKey]) && (i!=j)){ // if the fruit (compare key) is the same (has been found)
arr[j][addKey]+=arr[i][addKey]; // we sum
arr.splice(i, 1); // we get rid of row (from end to start i, not to mess with the offset of the loop)
break;
}
}
}
return arr;
}

Here is a quick example :
I make a simple function just to transform the flat array into an array of objects and then I put the two resting arrays into another array
var myArray1 = [ "Orange:10", "Orange:5", "Banana:20", "Apple:5" ];
var myArray2 = [ "Orange:5", "Banana:10", "Apple:15" ];
var myArray1b = arrayToObjectArray(myArray1);
var myArray2b = arrayToObjectArray(myArray2);
var myResult = [myArray1b,myArray2b];
console.log(myResult);
function arrayToObjectArray(arr){
var arr2 = arr.map(function(item) {
var items = item.split(":");
item = {};
item.fruit = items[0];
item.value = items[1];
return item;
});
return arr2;
}

Related

Javascript - Adding multiple values to keys

I am trying to find the places of each letter in a sentence by using "dictionaries". The problem is I want to find all the places that each letter is and not only the last one. I am very new to JavaScript and couldn't figure out the way to do it.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g,'');
var dict = {};
for (var i=0; i < stringArgument.length; i++ )
if (!stringArgument[i] in dict){
dict[stringArgument[i]] = [];
}else{
dict[stringArgument[i]] = [i+1]
}
return dict
}
var a = letters('Lost time is never found again.');
console.log(a);
naturally gives this output:
{ L: [ 1 ], o: [ 17 ], s: [ 10 ], t: [ 5 ]...
but it should give this:
{ L: [ 1 ], o: [ 2, 17 ], s: [ 3, 10 ], t: [ 4, 5 ]...
Also each letter is saved to the dictionary at the same order they appear in the sentence, how can I order the letters alphabetically?
What you need is a function that gets the positions of a character in a given string.
Try this:
function findAllPositions(char, content) {
var result = [];
let index = content.indexOf(char);
while(index !== -1) {
result.push(index);
index = content.indexOf(char, index + 1);
}
return result;
}
findAllPositions('o', 'Lost time is never found again.'); // Result =  [1, 20]
Using this we can update the letter function as follows:
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, '');
var dict = {};
for (const char of stringArgument) {
dict[char] = findAllPositions(char, stringArgument)
}
return dict;
}
letters('is again.')
/*
{
"i": [0, 5],
"s": [1],
"a": [2, 4],
"g": [3],
"n": [6],
".": [7]
}
*/
You need to have
parantheses for the check
if (!(stringArgument[i] in dict)) {
create an array if the above is true
push the postion to the array
For getting a sorted output, you could take the entries of the object, apply a sorting by taking the key and show the result in order.
Object have an insertation oder for not positive 32 bit numbers (like indixes) or symbols. The index like numbers are sorted by value and appears first in the object.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, '');
var dict = {};
for (var i = 0; i < stringArgument.length; i++) {
if (!(stringArgument[i] in dict)) {
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i + 1);
}
return dict;
}
var a = letters('Lost time is never found again.');
Object
.entries(a)
.sort(([a], [b]) => a.localeCompare(b))
.forEach(([key, positions]) => console.log(key, ...positions));
console.log(a);
First, for any item, if it is not in an empty array:
var notInDict = !(stringArgument[i] in dict);
If not in dict, then initialize an empty array and push the item in it using
dict[stringArgument[i]].push(i + 1);
Try this.
function letters(stringArgument) {
stringArgument = stringArgument.replace(/ /g, "");
var dict = {};
for (var i = 0; i < stringArgument.length; i++) {
var notInDict = !(stringArgument[i] in dict);
if (notInDict) {
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i + 1);
}
return dict;
}
var a = letters("Lost time is never found again.");
console.log(a);
you are assigning a new array at each iteration
dict[stringArgument[i]] = [i+1]
what you need to do is push the new position to existing array.
dict[stringArgument[i]].push(i+1)
also, remove the else block
function letters(stringArgument) {
stringArgument = stringArgument.toLowerCase().replace(/ /g,'');
var dict = {};
for (var i=0; i < stringArgument.length; i++ ){
if (!dict.hasOwnProperty(stringArgument[i])){
dict[stringArgument[i]] = [];
}
dict[stringArgument[i]].push(i+1);
}
//sorting
var letters = Object.keys(dict); //returns a array
letters.sort();
var sortedDic = {};
for(var i in letters) {
sortedDic[letters[i]] = dict[letters[i]];
}
return sortedDic;
}
var a = letters('Lost time is never found again.');
console.log(a);
for the first part you can also do that:
let sentence = 'Lost time is never found again.'
let tabLetters = [...sentence.replace(/ /g,'')].reduce((a,c,i)=>
{
if (!a[c]) a[c] = [i+1]
else a[c].push(i+1)
return a
},{})
document.write(JSON.stringify(tabLetters))

How to sort an array according to another array in javascript?

I count the words in a paragraph by frequency of occurrences now I need to sort them too for example [this : 2, is : 3, it : 1] to [is : 3, this : 2, it : 1]. I divided keys and values into two different arrays then I sorted an array of values now I want to sort an array of keys
console.log('app running');
function getFrequencyOfWord(word : string) {
let counting: any = {};
let wordSplit: any = word.split(' ');
wordSplit.forEach(function (word: any) {
if (counting[word]) {
counting[word]++;
}
else {
counting[word] = 1;
}
})
var arr1 = Object.keys(counting);
var arr2 = arr1.map((suboor)=> {
return counting[suboor];
});
for (var i : number = 0; i < arr2.length; i++) {
for (var j = 0; j < (arr2.length -i -1); j++) {
if (arr2[j] > arr2[j+1]) {
const lesser = arr2[j+1];
arr2[j+1] = arr2[j];
arr2[j] = lesser;
}
}
}
console.log(arr2);
console.log(arr1);
}```
You could try something like the following:
let word = "moo moo moo hello one two three one";
let wordSplit = word.split(' ');
var counting = [];
wordSplit.forEach(function (word) {
if (counting[word]) {
counting[word]++;
}
else {
counting[word] = 1;
}
})
console.log("Counting ...");console.log(counting);
function swap(json){
var ret = {};
for(var key in json){
let element = ret[json[key]] ;
//console.log("element");console.log(element);
if(element == undefined){
ret[json[key]] = element= [];
}
element.push(key);
//console.log("element");console.log(element);
}
return ret;
}
let result = swap(counting);
console.log("RESULT ...");console.log(result);
var finalResult = [];
for(var key in result){
finalResult = finalResult.concat(result[key]);
}
console.log("Final RESULT ...");console.log(finalResult);
Output
Word Count:
[moo: 3, hello: 1, one: 2, two: 1, three: 1]
Result:
{1: Array(3), 2: Array(1), 3: Array(1)}
1: (3) ["hello", "two", "three"]
2: ["one"]
3: ["moo"]
Final Result
0: "hello"
1: "two"
2: "three"
3: "one"
4: "moo"
Fiddle: https://jsfiddle.net/menelaosbgr/xe9u7mqk/33/
Update
The problem is that you actually have a map of object instead of an array. An array of objects would be something like [{is:3},{this:2},{it:1}] . It's not that difficult to do the conversion. However, I think it's better to have objects that are like this {word:X, count:x}. See below:
let word = "this this is is it is";
let wordSplit = word.split(' ');
var counting = [];
wordSplit.forEach(function (word) {
if (counting[word]) {
counting[word]++;
}
else {
counting[word] = 1;
}
})
console.log("Counting ...");console.log(counting);
function swap(json){
var ret = {};
for(var key in json){
let element = ret[json[key]] ;
//console.log("element");console.log(element);
if(element == undefined){
ret[json[key]] = element= [];
}
element.push({count:json[key], word:key});
//console.log("element");console.log(element);
}
return ret;
}
let result = swap(counting);
console.log("RESULT ...");console.log(result);
//Reverse it and make it into objects...
let reversedResult = Object.assign([], result ).reverse();
console.log("RESULT-REVERSED ...");console.log(reversedResult);
//Final Conatenated Array
var concatenatedArray = [];
for(var key in reversedResult){
concatenatedArray = concatenatedArray.concat(reversedResult[key]);
}
console.log("CONCATENATED-ARRAY ...");console.log(concatenatedArray);
Result:
0: {count: 3, word: "is"}
1: {count: 2, word: "this"}
2: {count: 1, word: "it"}
Fiddle: https://jsfiddle.net/menelaosbgr/xe9u7mqk/49/
This is not possible to sort array of keys according to array of values but you can do something to map right key to right value by checking if(arr[key] == arr[value]) and if key and value are equal then you can push that key value pair into new array.

Sorting key value pair on basis of another array

I have key value pairs like :
var x={1:Car,
2: Cycle,
3:John
}
This is response coming from JSON.[Object object]
I have array like :var arr=[1,3,2]
I want to sort x as per arr .
order should be : {1:Car,3:John,2:Cycle}
In javascript how to achieve this.
You don't need to sort them, just make a new empty array and populate it by getting the values of arr and using them as the index of x.
var x = {
1: 'Car',
2: 'Cycle',
3: 'John'
};
var arr = [1, 3, 2];
var output = [];
arr.forEach(function(item){
output.push(x[item]);
});
console.log(output);
Fiddle.
var order = function(obj, arr) {
var temp = {};
for (var i = 0; i < arr.length; i++) {
temp[i] = obj[arr[i]];
}
return temp;
}
var x = {
1: "Car",
2: "Cycle",
3: "John"
}
var arr = [1, 3, 2]
x = order(x, arr);
console.log(x);

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)

How do I return array of duplicate strings in array?

I need a function that takes in an array and will return an array with all the duplicates. I would prefer to use underscore if possible.
given the array:
[
"apple",
"apple",
"pear",
"pear",
"kiwi",
"peach"
]
I need to return an array
[
"apple",
"pear"
]
Many of the methods I've found will return a boolean and not an array of the duplicates.
For example
var fruits = ["apple","apple"];
var uniq_fruits = _.uniq(fruits);
var duplicates_exist = (fruits.length == uniq_fruits.length);
You could use _.countBy to get the word frequencies and then use _.reduce to collect up the values with a frequency greater than one:
function collect_dups(a, n, word) {
if(n > 1)
a.push(word);
return a;
}
var dups = _(words).chain()
.countBy()
.reduce(collect_dups, [])
.value();
Demo: http://jsfiddle.net/ambiguous/gKmfh/1/
Turn your list into a map, then turn the map into a list.
var fruits = ["apple", // ... ];
function fruitCounter(countMap, fruit) {
if (countMap[fruit] == null)
countMap[fruit] = 1;
else
countMap[fruit]++;
return countMap;
}
function dupFinder(dupList, count, fruit) {
if (count > 1)
dupList.push(fruit);
return dupList;
}
var dups = _.reduce(_.reduce(fruits, fruitCounter, {}), dupFinder, []);
It's sort-of unfortunate that there's nothing really like "filter" for the properties of an object, but it's not too bad with "reduce".
edit — a comment from someone better at Underscore than me points out that the inner "reduce" could be replaced by a simpler "countBy":
var dups = _.reduce(_.countBy(fruits, function(f) { return f; }), dupFinder, []);
var common = function(array){
var tally = function(array){
var make_object = {};
_.each(array, function(item){
make_object[item] = (typeof make_object[item] == "undefined") ? 1 : make_object[item] + 1;
});
return make_object;
}(array);
var duplicates = function(obj){
var duplicates = [];
_.each(obj, function(value, key){
if(value > 1){
duplicates.push(key);
}
});
return duplicates;
}(tally);
return duplicates;
};
The idea is very straight forward. Group the items by its value and then find which group having more than 1 items. Finally pick only one item from each group.
lst = [ "apple", "apple", "pear", "pear", "kiwi", "peach"];
var result = _.chain(lst)
.groupBy(function (i) { return i; })
.filter(function (v, k) { return v.length > 1; })
.map(function(v){return v[0]; })
.value();
>>["apple", "pear"]
where arr is your input, you just check to see if the element is a key on the obj object - if it is, pass it to the output array and reloop, otherwise add the key to the object:
function findDupes(arr) {
var obj = {}, newArr = [];
for (var i = 0, l = arr.length; i < l; i++) {
if (obj[arr[i]]) { newArr.push(arr[i]); continue; }
obj[arr[i]] = true;
}
return newArr;
}
var dupes = findDupes(arr);
Giving you have a simple one level array of strings, I would suggest to sort an array first and then loop through it trying to compare current item with the next one.
Something like this:
var fruit = [
"apple",
"apple",
"apple",
"pear",
"pear",
"cantalope"
];
var common = function(array){
var mySortedArray = array.sort();
var myResultArray = [];
for (var i = 0; i < mySortedArray.length - 1; i++)
if ( (mySortedArray[i + 1] == mySortedArray[i]) &&
(mySortedArray[i] != myResultArray[myResultArray.length-1]) )
myResultArray.push(mySortedArray[i]);
return myResultArray;
};
alert(common(fruit));
I started from this function : https://stackoverflow.com/a/840849/1636522
function getDuplicates(arr) {
var i,
len = arr.length,
out = [],
obj = {};
for (i = 0; i < len; i++) {
switch (obj[arr[i]]) {
case undefined: obj[arr[i]] = 1; break;
case 1: obj[arr[i]] = 2; out.push(arr[i]); break;
}
}
return out;
}

Categories