I have an array which contains the FileNames as New1, New2.... etc
I'm trying to code a function which returns me the new file name which is not present in the array and is the next consecutive number.
Let's say I have array as
Let array = [{"Name" : "New"},{"Name" : "New1"},{"Name" : "New3"}]
Then I want next new file name to be New2
How can I do this in java script?
Using the below function you will be able to pass the default filename and file array both. So this function will work for any kind of filenames and find the missing number in between if there is any.
function getNewFileName(FileArr, defaultName){
let isKeepTrying = true;
let fileName = defaultName;
let defaultFileName = defaultName;
let counter = 0;
let namearr= [];
for(let i=0; i<FileArr.length ; i++ ){
let newFileName = FileArr[i].Name;
namearr.push(newFileName);
}
do{
if(namearr.indexOf(fileName) > -1) {
counter += 1;
fileName = defaultFileName + counter;
isKeepTrying = true;
}
else {
isKeepTrying = false;
}
} while (isKeepTrying);
return fileName;
};
var files = [{"Name": "New"}, {"Name":"New1"}, {"Name":"New3"}]
console.log(getNewFileName(files,"New"))
This function should help you determine what is the number that is missing if you have a partially consecutive sequence. I've edited the sample array's objects so that the key is name, and not "Name".
let array = [{name: "New"},{name: "New1"},{name: "New3"}]
let nextNumber = (arr) => {
return arr
.map(o => o.name)
.map(n => n.substring(3))
.filter(s => s != "")
.map(s => parseInt(s))
.find((e, _i, a) => {
if (!a.includes(e + 1))
return true;
}) + 1
}
console.log(nextNumber(array))
YOu can create a substring and use forEach to loop the array .Then check the index with the substring
let array = [{
"Name": "New"
}, {
"Name": "New1"
}, {
"Name": "New3"
}];
array.forEach(function(item, index) {
if (index === 0) {
if (item.Name.slice(3) !== '') {
console.log("new" + index);
}
} else {
if (item.Name.slice(3) != index) {
console.log("new" + index);
}
}
})
Related
I would like to transform an array into another separing its items depending on a string data, and, when there are two or more items together and none of them is is the limit string data i would like to join then by "/". Something like this:
const stringLimit = "aa";
let arrayData =["b","c","aa","aa","d","c","aa","f"];
result:
arrayResult=["b/c","d/c","f];
I have try this, however, I think that there should be a better way
let stringItem;
let totalRouteDevice = new Array();
for (let index = 0; index < arrayData.length; index++) {
const item = arrayData [index];
if(item!=='aa' && item !== 'bb') {
stringItem = stringItem!=""?`${stringItem}/${item}`:stringItem
} else if(stringRouteItem!=="") {
totalRoute.push(stringItem);
stringItem ="";
}
}
I have try this, however, I think that there should be a better way
let stringItem;
let totalRouteDevice = new Array();
for (let index = 0; index < arrayData.length; index++) {
const item = arrayData [index];
if(item!=='aa' && item !== 'bb') {
stringItem = stringItem!=""?`${stringItem}/${item}`:stringItem
} else if(stringRouteItem!=="") {
totalRoute.push(stringItem);
stringItem ="";
}
}
Not saying this is better but you could group your data using reduce, splitting it by stringLimit, and then joining the groups by / as follows:
const stringLimit = 'aa'
const arrayData = ["b","c","aa","aa","d","c","aa","f"]
let arr = []
arrayData.reduce((acc, item, i) => {
if (item !== stringLimit) {
acc.push(item)
} else {
if (acc.length) {
arr.push(acc)
}
acc = []
}
if (item !== stringLimit && i === arrayData.length - 1) {
arr.push(acc)
}
return acc
}, [])
let result = arr.map((i) => i.join('/'))
console.log(result)
what is the best way to convert below array into a string and Name, value should be separated by : Json objects are separated by |.
let arr = [
{
"name":"abc",
"value":"21"
},
{
"name":"abcd",
"value":"212"
}
];
function arrToString(arr){
//logic
return "abc:21|abcd:212"
}
console.log(arrToString(ar));
Expected output: "abc:21|abcd:212"
I have used this logic but I don't like this. I need more efficient logic.
let arr = [{
"name": "abc",
"value": "21"
},
{
"name": "abcd",
"value": "212"
}
];
function setKey(arr) {
let temp = "";
arr.forEach((ele, index) => {
let name = ele.name;
let value = ele.value;
if (arr.length - 1 == index) {
temp = temp + name + ":" + value
} else {
temp = temp + name + ":" + value + "|";
}
});
console.log(temp);
}
setKey(arr);
function arrToString(arr){
let returnString = ''
arr.forEach((item, index) => {
if(index !== 0) returnString += '|'
returnString += `${item.name}:${item.value}`
})
return returnString
}
Hope this will solve your question
You can easily perform the conversion by exploiting the functional features of Javascript, in particular the map function:
function arrToString(arr){
return arr.map(x => x.name + ":" + x.value).join('|')
}
#danieleds'a answer with an arrow function :)
const arrToString = arr => arr.map(x => x.name + ":" + x.value).join('|')
You can use a combination of the map and join function like this:
function arrToString(arr) {
return arr.map(item => `${item.name}:${item.value}`).join("|")
}
In this case the map function, which is a higher-order function, applies a function for each item in the arr array. In this case, we create the desired string for each item. The join function combines all the strings (e.g. abc:21, abcd:212) together by separating the values with a pipe (|)
Here is one way with slice(which is used to remove characters from strings or elements from array):
function arrToString(arr){
let ans = "";
for(let i = 0 ; i < arr.length;i++){
ans += (arr[i].name + ":" + arr[i].value);
ans+= "|";
}
ans = ans.slice(0,-1);
return ans
}
In another simple way,
function objToStr(objArr){
let strArray = [];
objArr.forEach((item) => {
strArray.push(item.name+":"+item.value);
})
return strArray.join("|");
}
I have to loop through the object values and sort them in such a way that I remove number 1 & 2 (lets call it index) from Self and Spouse. Then reindex Child3 and Child4 to Child1 and Child2.
Though the Object got from API response looks like below it makes more sense to reindex them as I'll be displaying this information on the screen.
Object looks like below: This is just a sample data. This object is
dynamically created based on User household information
eligibilityMap: {
"CHIP": [
"CHILD3" // should be Child1
],
"APTC/CSR": [
"SELF1", //should be Self
"SPOUSE2", //should be Spouse
"CHILD4" //should be Child2
]
}
My question is how should I loop through this Object and just sort the child and reindex the same?
Expected Result:
newMapping: {
"CHIP": ["Child1"],
"APTC/CSR": ["Self, Spouse and Child2"]
}
CODE:
var sortedMember = Object.keys(eligibilityMap).reduce((acc, key) => {
//fetch the array for the given key
var array = eligibilityMap[key];
console.log('array', array);
var sortedArray = array.sort( function (firstValue, secondValue) {
if (firstValue.indexOf("SELF") >= 0) return -1;
if (secondValue.indexOf("SELF") >= 0) return 1;
if (firstValue.indexOf("SPOUSE") >= 0) return -1;
if (secondValue.indexOf("SPOUSE") >= 0) return 1;
return 0;
});
console.log("sortedArray", sortedArray)
acc[key] = sortedArray;
return acc;
}, {})
$scope.memberString = Object.keys(sortedMember).reduce(function (acc, key) {
var array = sortedMember[key]
var formattedString = array.reduce(function (memberAcc, member, index) {
if (member.indexOf("SELF") >= 0) {
return "Applicant"
}
if (member.indexOf("SPOUSE") >= 0) {
var delimiter = index > 0 ? ", " : "";
return memberAcc + delimiter + "Spouse"
}
if(index === 0) return member;
var delimiter = index === array.length - 1 ? " and " : ", ";
return memberAcc + delimiter + member //CHILD1
}, "");
console.log("STRING", key, formattedString)
acc[key] = formattedString;
return acc;
}, {});
RESULT: (But still not what I wanted)
MEMBERS STRING {CHIP: "CHILD4", APTC/CSR: "Applicant, Spouse, CHILD3 and CHILD5"}
You can check this approach. I've created a dataMapper to map the specific data with their new values.
var obj = {
"CHIP": [
"CHILD3", // should be Child1
],
"APTC/CSR": [
"SELF1", //should be Self
"SPOUSE2", //should be Spouse
"CHILD4" //should be Child2
],
"TEST": [
"SELF1",
"CHILD3"
]
};
// Code to support IE9
var i = 0;
var updatedObj = {};
var data = Object.keys(obj).map(function(key) {
var values = obj[key];
var memberArr = new Array();
var dataObj = values.reduce(function(store, value) {
var storeKey = value.replace(/[0-9]/g, '');
var number = Number(value.replace(/^\D+/g, ''));
if(storeKey !== 'SELF' && storeKey !== 'SPOUSE') {
var arr = new Array();
for(i = 0; i < number; i++) {
arr.push(storeKey);
memberArr.push(storeKey);
}
store[storeKey] = arr;
} else {
var anotherArr = new Array(storeKey);
memberArr.push(storeKey);
store[storeKey] = anotherArr;
}
return store;
}, {});
memberArr.sort(function(a, b) {
return b - a;
})
var sortedMemberArr = memberArr.map(function(member, index) {
return member+''+(index+1);
})
updatedObj[key] = sortedMemberArr;
})
console.log(updatedObj)
/*
// Code Using Modern Syntax
const data = Object.entries(obj).map(([key, value]) => {
const memberCount = value.reduce((store, val) => {
const key = val.replace(/[0-9]/g, '');
const number = +val.replace(/^\D+/g, '');
if(!['SELF', 'SPOUSE'].includes(key)) {
store[key] = Array(number).fill(key);
} else {
store[key] = [key];
}
return store;
}, {})
const sortedMembers = Object.values(memberCount).flat().sort((a, b) => b - a);
const sortedMembersWithNumber = sortedMembers.map((member, index) => `${member}${index+1}`)
return [key, sortedMembersWithNumber]
})
const updatedObj = Object.fromEntries(data);
console.log(updatedObj)
*/
I am trying to find values that commonly appear next to each other in an array.
E.G. given the array:
["dog","cat","goat","dog","cat","elephant","dog","cat","pig","seal","dog","cat","pig","monkey"]
it should return something similar to:
[[["dog","cat"],4],[["cat","pig"],2],[["dog","cat","pig"],2]]
Here is some better data: https://pastebin.com/UG4iswrZ
Help would be greatly appreciated. Here is my current failed attempt at doing something similar:
function findAssociations(words){
var temp = [],tempStore = [],store = [],found = false;
//loop through the words counting occurrances of words together with a window of 5
for(var i = 0;i<words.length-1;i++){
if(i % 5 == 0){
//on every fith element, loop through store attempting to add combinations of words stored in tempStore
for(var j = 0;j<5;j++){
temp = []
//create the current combination
for(var k = 0;k<j;k++){
temp.push(tempStore[k]);
}
//find if element is already stored, if it is, increment the occurrence counter
for(var k = 0;k<store.length;k++){
if(store[k][0]===temp){
found = true;
store[k][1] = store[k][1]+1;
}
}
//if it isn't add it
if(found == false){
store.push([temp,1]);
}
found == false;
}
tempStore = [];
} else {
//add word to tempStore if it i isnt a multiple of 5
tempStore.push(words[i]);
}
}
}
This script is doesn't remove combinations that appear once,it doesn't sort the output by occurrences, nor does it work. It is just an outline of how a possible solution might work (as suggested by benvc).
Here is a generic solution working with multiple group sizes.
You specify a range of group sizes, for example [2,4] for groups of 2 to 4 elements and a minimum number of occurrences.
The function then generates all groups of neighbours of the given sizes, sorts each group and counts the duplicates. The sorting step can be removed is the order in the groups matters.
The duplicates are counted by creating a dictionary whose keys are the group elements sorted and jointed with a special marker. The values in the dictionary are the counts.
It then returns the groups sorted by occurences and then by group size.
const data = ["dog","cat","goat","dog","cat","elephant","dog","cat","pig","seal","dog","cat","pig","monkey"];
function findSimilarNeighbors(groupSizeRange, minOccurences, data) {
const getNeighbors = (size, arr) => arr.reduce((acc, x) => {
acc.push([]);
for (let i = 0; i < size; ++ i) {
const idx = acc.length - i - 1;
(acc[idx] || []).push(x);
}
return acc;
}, []).filter(x => x.length === size);
const groups = [];
for (let groupSize = groupSizeRange[0]; groupSize <= groupSizeRange[1]; ++groupSize) {
groups.push(...getNeighbors(groupSize, data));
}
const groupName = group => group.sort().join('###'); // use a separator that won't occur in the strings
const groupsInfo = groups.reduce((acc, group) => {
const name = groupName(group);
acc[name] = acc[name] || {};
acc[name] = { group, count: (acc[name].count || 0) + 1 };
return acc;
}, {});
return Object.values(groupsInfo)
.filter(group => group.count >= minOccurences)
.sort((a, b) => {
const countDiff = b.count - a.count;
return countDiff ? countDiff : b.group.length - a.group.length;
})
.map(({ group, count }) => [group, count]);
};
console.log(findSimilarNeighbors([2, 4], 2, data));
console.log(findSimilarNeighbors([4, 4], 2, data));
Here is what I came up with. It only finds pairs, but you could modify it to find sets of 3, 4, etc, based on what you % by
const animals = ['dog','cat','goat','dog','cat','elephant','dog','cat','pig','seal','dog','cat','pig','monkey'];
let pairs = ',';
animals.forEach((animal, i) => {
let separator = ',';
if (i % 2 === 0) {
separator = ';'
}
pairs += animal + separator;
});
const evenPairs = pairs.split(',');
const oddPairs = pairs.split(';');
const allPairs = evenPairs.concat(oddPairs).map(pair => pair.replace(/[;,]/, ' '));
let result = {}
allPairs.forEach(pair => {
if (pair.length) {
if (result[pair] === undefined) {
result[pair] = 1;
} else {
result[pair]++;
}
}
});
results in:
dog: 1
cat elephant: 1
cat goat: 1
cat pig: 2
dog cat: 4
elephant dog: 1
goat dog: 1
monkey : 1
pig monkey: 1
pig seal: 1
seal dog: 1
https://stackblitz.com/edit/typescript-wvuvnr
You need to be clear what you mean by close and how close. Just looking at first neighbours you could try:
const findAssociations = words => {
const associations = {}
for (let i = 0; i < words.length - 1; i++) {
const word = words[i]
const wordRight = words[i+1]
const wordOne = word < wordRight ? word : wordRight;
const wordTwo = word < wordRight ? wordRight : word;
const keys = Object.keys(associations)
const key = `${wordOne}:${wordTwo}`
if (keys.indexOf(key) >= 0) {
associations[key]++
} else {
associations[key] = 1
}
}
const keys = Object.keys(associations)
const values = Object.values(associations)
const zipped = keys.map((key, index) => [key, values[index]])
zipped.sort((a, b) => a[1] < b[1] ? 1 : -1);
return zipped;
}
https://stackblitz.com/edit/js-3ppdit
You can use this function inside another function and add every time an element to ["dog", "cat"]
const arr = ["dog", "cat", "goat", "dog", "cat", "dog", "cat", "elephant", "dog", "cat", "pig", "seal", "dog", "cat", "pig", "monkey"]
const findArrayInArray = (arr1, arr2) => {
let count = 0,
arrString1 = arr1.join(""),
arrString2 = arr2.join("");
while (arrString2.indexOf(arrString1) > -1) {
count += 1;
arrString2 = arrString2.replace(arrString1, '');
}
return count;
}
console.log(`["dog", "cat"] exist ${findArrayInArray(["dog", "cat"], arr)} times`)
Assuming each item in the list is a delimiter of a set, and each set counts once for each item (i.e. ["dog", "cat", "goat"] counts as ["dog", "cat"] and ["dog", "cat", "goat"], and assuming you don't want any single occurrences, then here's one way:
const full_list = ["dog","cat","goat","dog","cat","dog","cat","elephant","dog","cat","pig","seal","dog","cat","pig","monkey"];
// create list of unique items
const distinct = (value, index, self) => {
return self.indexOf(value) ===index;
}
const unique_items = full_list.filter(distinct);
// get all patterns
var pre_report = {};
for (var i in unique_items) {
item = unique_items[i];
var pattern = [item];
var appending = false;
for (var j = full_list.indexOf(item) + 1; j < full_list.length; ++j) {
const related_item = full_list[j];
if (item == related_item) {
pattern = [item]
continue;
}
pattern.push(related_item);
if (pattern in pre_report) {
++pre_report[pattern];
} else {
pre_report[pattern] = 1;
}
}
}
// filter out only single occurring patterns
var report = {};
for (key in pre_report) {
if (pre_report[key] > 1) {
report[key] = pre_report[key];
}
}
console.log(report);
produces:
{ 'dog,cat': 5, 'dog,cat,pig': 2, 'cat,pig': 2 }
Here is my requirement. I was able to achieve to some level in java but we need to move it to typescript (client side).
Note: The below input is for example purpose and may vary dynamically.
Input
var input = ["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"];
We need to create an utility function that takes above input and returns output as below.
Output:
Should be string not an object or anything else.
"{ a { name, type }, b { city {name, zip } , desc }, c }"
any help is much appreciated.
I don't see that typescript plays any role in your question, but here's a solution for constructing the string you requested. I first turn the array into an object with those properties, then have a function which can turn an object into a string formatted like you have
const input = ["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"];
const arrayToObject = (arr) => {
return arr.reduce((result, val) => {
const path = val.split('.');
let obj = result;
path.forEach(key => {
obj[key] = obj[key] || {};
obj = obj[key];
});
return result;
}, {});
}
const objectToString = (obj, name = '') => {
const keys = Object.keys(obj);
if (keys.length === 0) {
return name;
}
return `${name} { ${keys.map(k => objectToString(obj[k], k)).join(', ')} }`;
}
const arrayToString = arr => objectToString(arrayToObject(arr));
console.log(arrayToString(input));
Here's another variation. Trick is to parse the strings recursively and store the intermediate results in an Object.
function dotStringToObject(remainder, parent) {
if (remainder.indexOf('.') === -1) {
return parent[remainder] = true
} else {
var subs = remainder.split('.');
dotStringToObject(subs.slice(1).join('.'), (parent[subs[0]] || (parent[subs[0]] = {})))
}
}
var output = {};
["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"].forEach(function(entry) {
dotStringToObject(entry, output)
});
var res = JSON.stringify(output).replace(/\"/gi, ' ').replace(/\:|true/gi, '').replace(/\s,\s/gi, ', ');
console.log(res)
// Prints: { a { name, type }, b { city { name, zip }, desc }, c }
You could do something like this:
var input = ["a.name", "a.type", "b.city.name" , "b.city.zip", "b.desc","c"];
var output = {};
for(var i =0; i < input.length; i+=2){
output[String.fromCharCode(i+97)] = {};
output[String.fromCharCode(i+97)].name = input[i];
output[String.fromCharCode(i+97)].type = input[i+1];
}
console.log(JSON.stringify(output));