I am making a tic-tac-toe game for fun and I am trying to do something a little different.
I am currently trying to check winning combinations by iterating through an array of stored tds that were grabbed with Jquery.
WIN_COMBINATIONS = [$("#square_0, #square_1, #square_2"),
$("#square_6, #square_7, #square_8"),
$("#square_0, #square_3, #square_6"),
$("#square_3, #square_4, #square_5"),
$("#square_1, #square_4, #square_7"),
$("#square_2, #square_5, #square_8"),
$("#square_0, #square_4, #square_8"), $("#square_6, #square_4, #square_2")]
So, basically, WIN_COMBINATIONS[0] is a winning combo. What is the best way to iterate through, and actually check the .html of the Jquery object?
Basically, I would like to do something like this
if (WIN_COMBINATIONS[0].html = "X", "X", "X") {
//do something here
}
Thanks for your help!
WIN_COMBINATIONS.forEach(function(combination){
if(combination.map(function(){return $(this).text()}).toArray().join("") == "XXX") {
console.log("winning combination")
}
})
if ES6 (ES2015) is OK than you can try reduce to find match
!!array.reduce(function(a, b){ return (a === b) ? a : NaN; });
Results:
var array = ["a", "a", "a"] => result: "true"
var array = ["a", "b", "a"] => result: "false"
var array = ["false", ""] => result: "false"
var array = ["false", false] => result: "false"
var array = ["false", "false"] => result: "true"
var array = [NaN, NaN] => result: "false"
Warning:
var array = [] => result: TypeError thrown
All credit to:
Lightness Races in Orbit
Related
I have a function called Action which receives an array parameter like this.
[
['X','','O'],
['O','','O'],
['X','X','']
]
I want this function to return an array like this where each empty section of the previous array is filled individually with a specific value, e.g Y.
[
[
['','Y',''],
['','',''],
['','','']
],
[
['','',''],
['','Y',''],
['','','']
],
[
['','',''],
['','',''],
['','','Y']
]
]
I know I can do that with forEach but it needs nested forEach which I think isn't very optimal. Is there any better way of doing that?
This should work:
let arr = [
['X','','O'],
['O','','O'],
['X','X','']
]
let res = []
arr.map((item, index)=>{
item.map((sub, indx) =>{
if(sub === ""){
let array_=
[
['','',''],
['','',''],
['','','']
];
array_[index][indx] = "Y";
res.push(array_)
}
})
})
console.log(res)
You could avoid nesting loops with the following steps
flatten the matrix into a 1-d array
get the indices of the empty sections
create new flatten 1-d arrays with empty indices from previous result marked as 'Y'
transform flatten 1-d arrays back to 3x3 matrix
const arr = [
["X", "", "O"],
["O", "", "O"],
["X", "X", ""],
]
const res = arr
.flat() // flatten the array
.map((section, i) => [section, i])
.filter(([section, _]) => section === "")
.map(([_, i]) => i) // get the indices of empty sections
.map(sectionIdx =>
Array.from({ length: 9 }, (_, i) => (i === sectionIdx ? "Y" : ""))
) // create new flattened array with empty indices marked as 'Y'
.map(flattenedArr => [
flattenedArr.slice(0, 3),
flattenedArr.slice(3, 6),
flattenedArr.slice(6, 9),
]) // turn back flatten array into 3x3 matrix
console.log(res)
I feel compelled to give the trivial answer, which is to continue using nested .forEach. This results in very readable code, which is, in my experience, more valuable than high performance code most of the time.
I'd begin by looping over each row and column of your input. Every time you encounter an matching cell (i.e. empty string, in your case), clone the input structure (using .map to '') and replace the matching element with the desired replacement string (e.g. 'Y').
const input = [
['X','','O'],
['O','','O'],
['X','X','']
]
const result = [];
input.forEach((row, iRow) => row.forEach((col, iCol) => {
if (col == '') {
const clone = input.map(row => row.map(col => ''));
clone[iRow][iCol] = 'Y';
result.push(clone);
}
}));
console.log(result);
I have an array
input = ["Hi","Bye","Hello","Jose","Juan",null,"How","","Disco"]
I want to always place the word "Bye" to the end of the joined string
I have tried with
input.filter(Boolean).join("#"))
expected output
"Hi#Hello#Jose#Juan#How#Disco#Bye"
I am looking for the best efficient way, or if there is a way to add a filter function along with Boolean filter
Use a filter function that compares with Bye after performing the boolean test.
Then append #Bye to the end of the result.
input = ["Hi", "Bye", "Hello", "Jose", "Juan", null, "How", "", "Disco"];
console.log(input.filter(s => s && s != 'Bye').join("#") + '#Bye');
1) Filter input array that are not empty, null and along with filter you can count of Bye(There can be multiple Bye)
2) Create a new array that only contains Bye using Array.from and append it after the filtered array.
3) Then, at last, you can join array.
const input = ["Hi", "Bye", "Hello", "Jose", "Juan", null, "How", "", "Disco"];
let length = 0;
const result = input
.filter((s) => {
if (s === "Bye") ++length;
return s && s !== "Bye";
})
.concat(Array.from({ length }, () => "Bye"))
.join("#");
console.log(result);
Sort the Byes to the end?
const input = ['Hi', 'Bye', 'Hello', 'Jose', 'Juan', null, 'How', '', 'Disco'];
const output = input
.filter(Boolean)
.sort((a, b) => (a === 'Bye') - (b === 'Bye'))
.join('#');
console.log(output);
If it is a string then one way to get the result is to
const outputString=input.filter(Boolean).join("#"))+"#bye"
I am new to javascript and I tried like using distinct but its not what im looking for
example array:
let arr = [ {key:"1",value:"dog"},
{key:"1",value:"dog"},
{key:"2",value:"cat"},
{key:"3",value:"bird"},
{key:"3",value:"bird"},
]
on the code I try is its just removing the duplicate like
[ {key:"1",value:"dog"},
{key:"2",value:"cat"},
{key:"3",value:"bird"}, ]
how can I get only the
[ {key:"2",value:"cat"} ]
what I mean is only the one who have no duplicate and its removing those array that have the exact same?
You can map your objects to stringified versions of your objects so you can then use .indexOf and .lastIndexOf() to compare if the object found appears in different locations in your array, if the last and first index appear in the same location then it can be said that they're the same object (ie: a duplicate doesn't exist) and can be kept in your resulting array like so:
const arr = [{key:"1",value:"dog"},{key:"1",value:"dog"},{key:"2",value:"cat"},{key:"3",value:"bird"},{key:"3",value:"bird"}];
const searchable = arr.map(JSON.stringify);
const res = arr.filter((obj, i) => {
const str = JSON.stringify(obj);
return searchable.indexOf(str) === searchable.lastIndexOf(str);
});
console.log(res);
If you can use Javascript libraries such as underscore or lodash, I recommend having a look at _.xorBy function in their libraries. From lodash:
_.xorBy([arrays], [iteratee=_.identity])
Basically, you pass in the array that in here is an object literal and you pass in the attribute that you want to all occurrences of remove duplicates with in the original data array, like this:
var data = [ {key:"1",value:"dog"}
, {key:"1",value:"dog"}
, {key:"2",value:"cat"}
, {key:"3",value:"bird"}
, {key:"3",value:"bird"}
];
var non_duplidated_data = _.xorBy(data, 'key');
Source - https://lodash.com/docs/4.17.14#xorBy
You can use reduce and Map
let arr = [{key:"1",value:"dog"},{key:"1",value:"dog"},{key:"2",value:"cat"},{key:"3",value:"bird"},{key:"3",value:"bird"}]
let mapper = arr.reduce( (op,inp) => {
let {key} = inp
op.set(key, op.get(key) || {value: inp, count:0})
op.get(key).count++
return op
},new Map())
let final = [...mapper.values()].reduce((op,{value,count}) => {
if(count === 1){
op.push(value)
}
return op
},[])
console.log(final)
Using the "find" method, you will get exactly what you are looking for "{key:"2",value:"cat"}".
arr.find((item, index) => {
const foundDup = arr.find((s, sIndex) => sIndex !== index && s.key === item.key);
return !foundDup;
});
If you don't mind using a library, I strongly suggest using the "ramda" library.
const arr = [ {key:"1",value:"dog"}
, {key:"1",value:"dog"}
, {key:"2",value:"cat"}
, {key:"3",value:"bird"}
, {key:"3",value:"bird"}
];
const result = R.uniq(arr);
result will be:
[{"key": "1", "value": "dog"}, {"key": "2", "value": "cat"}, {"key": "3", "value": "bird"}]
you can use "lodash" or other similar libraries too.
I'm trying to take an object that looks like this : [ '1,23' , '4,56' , '7,89' ] to an Array. Although it looks like one, it isnt. It is an typeof acuses it as a object.
I tried toArray, forEach, splice with comma (cant due to the middle numbers).
Anyway, can anyone give me a hand. I'm trying really hard with something that , at least, looks easy.
JavaScript's typeof does not have a separate value for array, it returns "object". You can check if a value is an array with the Array.isArray function.
var a = [1, 2, 3];
typeof a == "object"
Array.isArray(a) == true
Something like this, by replacing each element's , with . and then parsing.
const input = ['1,23', '4,56', '7,89']
const outputString = input.map(it => it.replace(',', '.'))
const outputFloat = input.map(it => it.replace(',', '.')).map(it => parseFloat(it))
console.log(outputString)
console.log(outputFloat)
To convert the array of strings to an array of numbers, you can use map and parseFloat to get the strings to numbers as well as replace to swap the "," for a "." for each string..
var arr = [ '1,23' , '4,56' , '7,89' ];
var newArr = arr.map(item => parseFloat(item.replace(/,/,'.')))
console.log(newArr); // gives [1.23, 4.56, 7.89]
[["Django UnChainers","AA-24010"],["General","AA-26191"]]
I have one array in above form. I want to retrieve all the value with prefix AA (which are in the second position). Is there any way where I can fetch the value by passing prefix?.
I know the way where I can get the value by passing index but may be tomorrow index can get change so is it possible to fetch the value by passing prefix?
In case OP wants a function to do this.
function(arr, pattern){
return arr.map(function(x){
return x.filter( word => ~ word.indexOf(pattern))
});
}
var arr =
[ [ "Django UnChainers", "AA-24010" ], [ "General", "AA-26191" ]];
var list = arr.map(function(x){
if(~(x[1].indexOf('AA'))){
return x[1];
}
});
console.log(list);
In case the index changes in future, iterate through each string and check for the "AA" string. Check the below code.
var arr =
[ [ "Django UnChainers", "AA-24010" ], [ "General", "AA-26191" ]];
var list = arr.map(function(x){
return x.filter( word => ~ word.indexOf('AA'))
});
console.log(list);
this is shorter
var = [nested array]
a.filter(x => x[1].startsWith('AA'))
//in case you are not sure about the index
a.filter(x => x.filter(y => y.startsWith('AA').length > 0))