Search in json array - javascript

I am new to json. My json array
[{"seat_number":"834"},{"seat_number":"8F3"},{"seat_number":"891"},
{"seat_number":"814"},{"seat_number":"4081"},{"seat_number":"8F1"},
{"seat_number":"8F9"},{"seat_number":"4039"},{"seat_number":"0"},
{"seat_number":"509"},{"seat_number":"662"},{"seat_number":"561"},
{"seat_number":"791"},{"seat_number":"849"}]
I want to find seat number already exist in array.
if(($scope.employeeSeat.seat_array.indexOf($scope.employeeData.new_seat_number))>-1)
{
alert('Seat number is already assigned.Please Check');
}
What is wrong?

You can do it the hard way if you want
var data = [
{"seat_number":"834"},{"seat_number":"8F3"},
{"seat_number":"891"},{"seat_number":"814"},
{"seat_number":"4081"},{"seat_number":"8F1"},
{"seat_number":"8F9"},{"seat_number":"4039"},
{"seat_number":"0"},{"seat_number":"509"},
{"seat_number":"662"},{"seat_number":"561"},
{"seat_number":"791"},{"seat_number":"849"}
];
function matchingSeat(x) {
return data.some(function(elem) {
return elem.seat_number === x;
});
}
console.log("831", matchingSeat("834")); // 834 true
console.log("8F3", matchingSeat("8F3")); // 8F3 true
console.log("999", matchingSeat("999")); // 999 false
I think that's a total pain tho. Once you have some reusable utility functions at your disposal, this problem becomes a lot easier to solve.
Don't freak out: the ES5 solution is below
// ES6
// reusable lib
let prop = y => x => x[y];
let comp = f => g => x => f(g(x));
let eq = y => x => x === y;
let some = f => xs => xs.some(f);
Now write some helpers to solve your task
let eqSeat = x => comp(eq(x))(prop("seat_number"));
let hasSeat = comp(some)(eqSeat);
Check it out
console.log("831", hasSeat("834")(data)); // 831 true
console.log("8F3", hasSeat("8F3")(data)); // 8F3 true
console.log("999", hasSeat("999")(data)); // 999 false
Here's the same code in ES5
// ES5
// reusable lib
var prop = function prop(y) {
return function (x) {
return x[y];
};
};
var comp = function comp(f) {
return function (g) {
return function (x) {
return f(g(x));
};
};
};
var eq = function eq(y) {
return function (x) {
return x === y;
};
};
var some = function some(f) {
return function (xs) {
return xs.some(f);
};
};
Your helpers
var eqSeat = function eqSeat(x) {
return comp(eq(x))(prop("seat_number"));
};
var hasSeat = comp(some)(eqSeat);
Try it out
console.log("831", hasSeat("834")(data)); // 831 true
console.log("8F3", hasSeat("8F3")(data)); // 8F3 true
console.log("999", hasSeat("999")(data)); // 999 false

Note that ({a:10}) !== ({a:10}), therefore your indexOf won't work. See this related question.
Knowing that, there are several ways to do this (assuming typeof $scope.employeeData.new_seat_number === 'string'):
1) Use a for-loop:
for (var i = 0; i < $scope.employeeSeat.seat_array.length; i++) {
if ($scope.employeeSeat.seat_array[i].seat_number === $scope.employeeData.new_seat_number) {
alert('Seat number is already assigned.Please Check');
}
}
2) Use .some:
if ($scope.employeeSeat.seat_array.some(function(seat) { return seat.seat_number === $scope.employeeData.new_seat_number; })) {
alert('Seat number is already assigned.Please Check');
}
Note: .some is the best answer other than the good old for-loop in my opinion. The rest are explorations of the Array API.
3) Use .findIndex:
if ($scope.employeeSeat.seat_array.findIndex(function(seat) { return seat.seat_number === $scope.employeeData.new_seat_number; }) !== -1) {
alert('Seat number is already assigned.Please Check');
}
4) Use .find:
if ($scope.employeeSeat.seat_array.find(function(seat) { return seat.seat_number === $scope.employeeData.new_seat_number; })) {
alert('Seat number is already assigned.Please Check');
}
Note: .find and .findIndex are experimental technologies. Check their compatibility tables to see if .find is available for your browser. If not, use their poly fills.
5) Use .map:
if ($scope.employeeSeat.seat_array.map(function(seat) { return seat.seat_number; }).indexOf($scope.employeeData.new_seat_number)) !== -1) {
alert('Seat number is already assigned.Please Check');
}
Note: Using .map will be much slower as .map iterates through the array running a function that will be used to create a brand new array.

for(var i = 0; i < myjson.length; i++)
{
if(myjson[i].seat_number == expectednumber)
{
alert('Seat number is already assigned.Please Check')
}
}

the item in your array is a object, so you can not use indexOf to find the seat_number.
you can try:
for(var i=0; i<$scope.employeeSeat.seat_array.length; ++i){
if($scope.employeeData.new_seat_number == $scope.employeeSeat.seat_array[i].seat_number){
alert('Seat number is already assigned.Please Check');
}
}

You can use array find prototype. You may find detail on this method here.
Example:
var items = [{"seat_number":"834"},{"seat_number":"8F3"},{"seat_number":"891"},{"seat_number":"814"},{"seat_number":"4081"},{"seat_number":"8F1"},{"seat_number":"8F9"},{"seat_number":"4039"},{"seat_number":"0"},{"seat_number":"509"},{"seat_number":"662"},{"seat_number":"561"},{"seat_number":"791"},{"seat_number":"849"}];
var newSeatNumber = $scope.employeeData.new_seat_number;
var result = items.find(function(item) {return item.seat_number == newSeatNumber ;})
console.log(result); // Object { seat_number="791"} if found, else undefined
if(result)
{
//Do your stuff. Item exits in array
}

Try this. Make use of filter(). If arr is empty, then it should show the alert.
var arr=$scope.employeeSeat.seat_array.filter(function(item){
return $scope.employeeData.new_seat_number == item.seat_number;
})
if(!arr.length){
alert('Seat number is already assigned.Please Check');
}
You can also make use of some().
var bool=$scope.employeeSeat.seat_array.some(function(item){
return $scope.employeeData.new_seat_number == item.seat_number;
})
if(bool){
alert('Seat number is already assigned.Please Check');
}

Why do you need such a JSON Structure ?
I've changed the structure a little.
{
"seat_numbers" :["894", "900", "814", "591", "789", ..]
}
Load your JSON using javascript/jquery
var yourSearchingSeat = "900";
$.getJSON( "ajax/test.json", function( data ) {
var seat_numbers = data.seat_numbers
for (i=0; i<seat_numbers.length;i++) {
if (seat_numbers[i] == yourSearchingSeat) {
console.log("Seat number"+yourSearchingSeat+" already exists");
}
}
});

Related

Reset loop with condition

I'm coding project with codewars and have a trouble. This function has to check if parentheses in string are valid. My problem is when i assign i = 0 in function valid pair it's doesnt work . I tried assign it below if statement and then my loop is infinite. My idea is valid pairs and then start over and over while parens.lenght will be <= 2 then i know that there left a pair and i can nothing to do with it. Could you help me?
// "()" => true
// ")(()))" => false
// "(" => false
// "(())((()())())" => true
const validPair = (parens) => {
console.log(parens);
for (let i = 0; i < parens.length; i++) {
if (parens[i] == '(' && parens[i + 1] == ')') {
parens.splice(i, 2);
i = 0;
console.log(parens.length);
}
if (parens.length <= 2) {
console.log(parens);
}
}
console.log(parens);
};
function validParentheses(parens) {
let validLength = 0;
parens = parens.split('');
parens.forEach((el) => {
if (el == '(') {
validLength++;
} else {
validLength--;
}
});
if (validLength != 0) {
return false;
} else {
validPair(parens);
}
}
console.log(validParentheses('(()))(()'));
I will be updating this code but i stuck in this moment and dont know what to do.
You've overcomplicated things
Simply counting is enough
// "()" => true
// ")(()))" => false
// "(" => false
// "(())((()())())" => true
function validParentheses(parens) {
let lefts = 0
for (const par of parens) {
if (par === '(') {
lefts += 1
} else {
lefts -= 1
}
if (lefts < 0) return false
}
if (lefts !== 0) return false
return true
}
console.log(validParentheses('()'));
console.log(validParentheses('(()))(()'));
console.log(validParentheses('('));
console.log(validParentheses('(())((()())())'));
Approach:
The idea is to use stack. so when you get ( you need to push it to stack and when you get ) you need to pop it. And at the end just need to check stack is still empty or not. if stack is empty that means parentheses are valid.
Edge case:
When there's no element in the stack and you have ) that means there's no ( bracket to match with it. so it returns false.
const validParentheses = (str) => {
const stack = [];
for (let parentheses of str) {
if (parentheses == '(') stack.push(parentheses);
else {
if (!stack.length) return false;
stack.pop();
}
}
return !stack.length;
}
console.log(validParentheses("()"));
console.log(validParentheses(")(()))"));
console.log(validParentheses("("));
console.log(validParentheses("(())((()())())"));

Javascript. I am trying to use .findIndex() but I get the following message: TypeError: a is not a function

I have ‘array magazine’ and ‘string ransomNote’. And want to access an element of the array based on an element from the string.
This is what I am trying: magazine.findIndex(ransomNote[i])
var canConstruct = function(ransomNote, magazine){
magazine = magazine.split('');
//console.log(magazine);
for(let i = 0; i < ransomNote.length; i++){
if (magazine.includes(ransomNote[i])){
element_to_erase = magazine.findIndex(ransomNote[i]);
magazine = magazine.splice(element_to_erase , 1);
//console.log(magazine);
continue;
} else {
return false;
}
}
return true;
};
console.log(canConstruct('aa', 'aab'));
findIndex takes a function as an argument, and you are passing it a string
you need to do
magazine.findIndex((magazineString) => magazineString === ransomNote[i])
Or just use indexOf as its pointed in the comments, and probably validate if that returns something other than -1 (indexOf) or undefined (findIndex) in either case.
Instead of converting the input string magazine to an array, you can use magazine.search directly -
const removeCharAt = (str = 0, pos = 0) =>
str.substr(0, pos) + str.substr(pos + 1)
const canConstruct = (ransomNote = "", magazine = "") => {
for (const char of ransomNote) {
const pos = magazine.search(char)
if (pos >= 0)
magazine = removeCharAt(magazine)
else
return false
}
return true
}
console.log(canConstruct('aa', 'aab'))
// true
console.log(canConstruct('az', 'aab'))
// false
console.log(canConstruct('stay inside', 'diet coke on sale this sunday'))
// true
There is another issue. While splice, u don't need to reassign. Splice modify the same array.
You can simplify using array.every.
var canConstruct = function (ransomNote, magazine) {
magazine = magazine.split("");
return ransomNote.split("").every((rChar) => {
const rIndex = magazine.indexOf(rChar);
if (rIndex !== -1) {
magazine.splice(rIndex, 1);
return true;
}
});
};
console.log(canConstruct("aa", "aab"));
console.log(canConstruct("az", "aab"));

check that a word is an isogram with pure javascript

How do i check that a given word is an isogram with pure javascript, using a function. the function must return true or false.
An isogram is a word with a repeated character.
I know this code works, but i need a better solution.
function isIsogram(word){
x = false; y = false;
for(i = 0; i < word.length; i++){
wordl = word.substring(0,i)
wordr = word.substring(i)
x = wordl.includes(word.charAt(i))
y = wordr.includes(word.charAt(i))
//console.log(x,wordl,wordr)
}
return x&&y
}
isIsogram("thomas");//False
isIsogram("moses"); //True
Remove the duplicate letter from string then check both length. if same its an isogram.
function isIsogram(str){
return str.split('').filter((item, pos, arr)=> arr.indexOf(item) == pos).length == str.length;
}
console.log(isIsogram('thomas'));
console.log(isIsogram('moses'));
One way of doing this!
function isIsogram(str){
return !str.match(/([a-z]).*\1/i);
}
Here is a simple approach using .split() and .every():
let isIsogram = (str) => str.split("").every((c, i) => str.indexOf(c) == i);
console.log(isIsogram("thomas")); /* no repeating letter */
console.log(isIsogram("moses")); /* s repeat 2 times */
console.log(isIsogram("hello")); /* l repeat 2 times */
console.log(isIsogram("world")); /* no repeating letter */
console.log(isIsogram("a b c")); /* space character repeat 2 times */
Docs:
String.prototype.split()
String.prototype.indexOf()
Array.prototype.every()
Building on kishea's answer:
function isIsogram(sWord)
{
for (iCharIndex = 0; iCharIndex < sWord.length; iCharIndex++)
if (sWord.substring(iCharIndex + 1).includes(sWord.charAt(iCharIndex)))
return false;
return true;
}
If the character at the current position (charAt) is found (includes) to the right of the current position (substring), false is returned. Otherwise the loop runs to the end and true is returned.
const isIsogram = (word) => {
return new Set(word.toLowerCase()).size === word.length
}
console.log(isIsogram('Thor'));//true
console.log(isIsogram('Loki'));//true
console.log(isIsogram('America'));//false
function isIsogram(str) {
return new Set(str.toUpperCase()).size == str.length
}
What about :
> function isIsogram(word) {
... var a = word.split('')
... var b = Array.from(new Set(a))
... return a.length === b.length;
... }
undefined
> isIsogram("mesos")
false
> isIsogram("thomas")
true
Or better (checking each char only once) :
> function isIsogram2(word) {
... for(var i=0,len=word.length-1;i<len;++i) {
..... var c = word[i]
..... if(word.indexOf(c,i+1) !== -1) return false;
..... }
... return true;
... }
undefined
> isIsogram2("mesos")
false
> isIsogram2("thomas")
true
function isIsogram(word){
return !/(.).*\1|\d/i.test(word)
}
var str=prompt('Enter a string');
var strlen=str.length;
for(i=0;i<strlen;i++){
var stc=str.charAt(i);
var flag=0;
for(j=0;j<strlen;j++){
var stk=str.charAt(j);
if(stc==stk){
flag=flag+1;
}
}
if(flag!=1){
break;
}
}
if(flag!=1){
alert('It is not an isogram');
}
else{
alert('It is an isogram');
}
While given a word, this function if splits the word into two,
That is wordl and wordr respectively.
Both splittings are checked to include a character in the original word. If wordl and wordr both contain any character in the original word. Then surely this is an isogram
function isIsogram(word){
x = false; y = false;
for(i = 0; i < word.length; i++){
wordl = word.substring(0,i)
wordr = word.substring(i)
x = wordl.includes(word.charAt(i))
y = wordr.includes(word.charAt(i))
//console.log(x,wordl,wordr)
}
return !x&&y
}
isIsogram("thomas");//True
isIsogram("moses"); //False
const isIsogram = (string) => {
const lowerCased = string.toLowerCase()
const result = lowerCased.split('').every((v,i)=>lowerCased.indexOf(v)===i)
return result
}
console.log(isIsogram('ambidExtRously')) // true
console.log(isIsogram('patteRN')) // false
function isIsogram(word) {
let uniqueCharacters = new Set(word.split(''));
uniqueCharacters = Array.from(uniqueCharacters); //get all the unique char
let charFreq = {}; //e.g {a:2, b:3}
for (element of uniqueCharacters) {
charFreq[element] = 0;
} //set the frequency of each char to zero
function updateFrequency(element) {
charFreq[element] += 1;
}//callback used directly below
word.split('').forEach(updateFrequency); //for each char encountered, update frequency
let frequencyOfCharacter = [];
for (keys in charFreq) {
frequencyOfCharacter.push(charFreq[keys]);
}
function equal(item) {
return item === frequencyOfCharacter[0];
}
//check if all the frequencies are the same, an isogram means all characters occur at the same frequency
return frequencyOfCharacter.every(equal);
}
console.log(isIsogram('try'), isIsogram('baba'), isIsogram('tests'));

RangeError: Maximum call stack size error in JS function

function findRandomDayIndex() {
var dayindex = _.random(0, 39);
var slot = dayslots[dayindex]; // array of 40 objects
if(slot.filled === true || slot === undefined) {
return findRandomDayIndex();
} else {
return dayindex;
}
}
I get the error:
RangeError: Maximum call stack size exceeded iteration of the same function
How can better write the function?
You might try out this version
function findRandomDayIndex()
{
var dayindex = Math.random(0, 39);
while( ( slot = dayslots[dayindex] ) == null )
dayindex = Math.random(0, 39);
return dayindex ;
}
Please check the consistence of dayslot, in order to prevent infinite while-looping anyway
You don't need recursion to do this. With a little refactoring you can map your array to save indexes, then filter undefined and filled values and then get random item from that new array, e.g.:
function findRandomDayIndex() {
var notFilled = dayslots.map(function(value, index) {
return {
value: value,
index: index
};
}).filter(function(day) {
return day.value !== undefined && !day.value.filled;
});
if (!notFilled.length) {
// all items of dayslots are undefined or filled
// handle this case here
}
var dayindex = _.random(0, notFilled.length - 1);
return notFilled[dayindex].index;
}
Here's one that handles when all dayslots are filled. The sample code returns -1, but you can update it to return anything.
function findRandomDayIndex() {
// Create an array of indexes for items that aren't filled
var m = _.map(dayslots, function(v, k) {
if (!v.filled) {
return k;
}
});
// The array will have undefined for those already filled, so we use lodash without to remove them
m = _.without(m, undefined);
if (m.length === 0) {
// Handle when all slots are filled
return -1;
} else {
// return a random index
return m[_.random(0, m.length)];
}
}
// Lets create some test data
var dayslots = [];
for (var i = 0; i < 40; i++) {
dayslots.push({
filled: false
});
}
// Test our function
console.log(findRandomDayIndex());
If you change the filled to true, then you'll get a -1.
As #CodeiSir commented since no slot was free code was going into infinite loop. So I changed the code as below and it works fine. Thank you!
if (_.findWhere(dayslots, {filled: false}) !== undefined) {
var dayindex = _.random(0, 39);
var slot = dayslots[dayindex];
console.log(dayslots.length);
if(slot.filled === true || slot === undefined) {
return findRandomDayIndex();
} else {
return dayindex;
}
}

RxJS and Unreachable Elements

I have a scenario where given an observable, I would like to know of any elements that never reach any subscribers (ex. filtered out) and take action based on that. What would be the best approach to achieve something like this?
Option # 1
Use a combination of publish and function composition.
var Rx = require('rx')
log = console.log.bind(console),
source = Rx.Observable.interval(100).take(100);
published = source.publish(),
accepted = published.where(condition),
rejected = published.where(not(condition));
accepted.subscribe(log.bind(undefined, 'accepted: '));
rejected.subscribe(log.bind(undefined, 'rejected: '));
published.connect();
function condition (x) {
return x % 4 === 0;
}
function not (func) {
return function () {
return !func.apply(this, arguments);
}
}
Option # 2
Tag (mutate) the events and filter at the last second.
var Rx = require('rx')
log = console.log.bind(console),
source = Rx.Observable.interval(100).take(100);
source
.map(toAcceptable)
.doAction(function (x) {
x.acceptable = x.acceptable && condition1(x.value);
})
.doAction(function (x) {
x.acceptable = x.acceptable && condition2(x.value);
})
.doAction(function (x) {
log(x.acceptable ? 'accepted:' : 'rejected:', x);
})
.subscribe();
function condition1 (x) {
return x % 4 === 0;
}
function condition2 (x) {
return x % 3 === 0;
}
function toAcceptable (x) {
return {
acceptable: true,
value: x
};
}

Categories