I want delete array from array of arrays without iterate on them.
the first array is like this :
array1 = [
[
[{"id":"A1","y":12},{"id":"A4","y":12}],
[{"id":"A2","y":1}],
[{"id":"A3","y":6}]
]
the second array is :
array2 = [{"id":"A1","y":12},{"id":"A4","y":12}]
I use javascript and i want delete array2 from array1.
So sorry for wrong description by the way i found that in my exemple the second array array is
array2 = [{ "id": "A1", "y": 12 }, { "id": "A4", "y": 2 }]
So the two arrays have just one columns which is equal. How i can delete array1 from array2 even they have just one attribute which is equal ?
Thank you.
splice is usually used to remove a particular item from the array. I think you want to do something like this:
var array = [
[{"name": "sik", "gender": "male"}],
[{"name": "sug", "gender": "female"}],
[{"name": "hyd", "gender": "male"}]
];
// it removes the second array from the array: removes the female one.
array.splice( 1, 1 );
Description: The function splice takes two arguments, first one is for the index of item, and second one until how much you want to delete.
For Example: splice( 2, 5 ) - means that: from the index 2, keep deleting until 5 items.
Hope this helps, Thanks.
Feels weird, but you can check every element of the array and match to the second array. Either way you need to iterate through your array. You can't simply type array1[i] == array2, you need to check it differently. A hack is to stringify them as JSON and compare strings, but there are other methods you can use to compare arrays.
Here is a simple demo with a for loop
array1 = [
[{ "id": "A1", "y": 12 }, { "id": "A4", "y": 12 }],
[{ "id": "A2", "y": 1 }],
[{ "id": "A3", "y": 6 }]
]
array2 = [{ "id": "A1", "y": 12 }, { "id": "A4", "y": 12 }]
l = array1.length
for (var i = 0; i < l; i++) {
// if arrays match
if (JSON.stringify(array1[i]) == JSON.stringify(array2)) {
// delete the element at `i` position
array1.splice(i, 1);
i--;
l--;
// break; // if you can guarantee that no more instances will occur
}
}
console.log(array1)
In Plain Javascript, we cannot filter them. This will work if u are dealing with valued datatypes. Here you are comparing arrays which are a referenced datatype. so here we need to write our own search stack
function searchForArray(haystack, needle){
var i, j, current;
for(i = 0; i < haystack.length; ++i){
if(needle.length === haystack[i].length){
current = haystack[i];
for(j = 0; j < needle.length && needle[j] === current[j]; ++j);
if(j === needle.length)
return i;
}
}
return -1;
}
var arr = [[1,3],[1,2]];
var n = [1,3];
console.log(searchForArray(arr,n));
You can refer this question which has some reference resources too.
Check whether an array exists in an array of arrays?
I know you asked for a solution without iteration, but i just thought to give an idea of references which may be useful for u.
Related
I want to check if two dates are within a range of each other, and reorder my array. I need to compare the dates from an array with the current date.
I have this:
var currentDate = new Date(); /* current date = 2021/08/18 */
listOfObjects = [ { "user": "John", "date": "2021-08-20" }, { "user": "Bob", "date": "2021-08-17" }, { "user": "Joe", "date": "2021-08-09" } ]
The return shoud be like this:
[ { "user": "Bob", "date": "2021-08-17" }, { "user": "John", "date": "2021-08-20" }, { "user": "Joe", "date": "2021-08-09" } ]
In JavaScript, an array is sorted by sorting the textual representation of its items.
The default sort order is ascending, built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values. (Source: Array.prototype.sort() - JavaScript | MDN)
See following example:
const numbers = [1, 30, 4, 21, 100000];
numbers.sort();
console.log(numbers);
We see that the output is the array with alphabetically sorted numbers:
1, 100000, 21, 30, 4
In most cases, this is not what we want (or what most people expect). To sort numbers numerically, we pass a custom compare function to sort:
function i_cmp(a, b) {
let d = a-b;
if (d < 0)
return -1;
if (d > 0)
return 1;
return 0;
}
numbers.sort(i_cmp);
console.log(numbers);
output:
1,4,21,30,100000
To sort an array by a criterion that depends on further conditions, it's handy to pass a function bound to runtime values that is created by another function. Here we sort items by their absolute distance of a fixed value x.
function d_cmp(x) {
return function(a, b) {
let d = Math.abs(a-x)-Math.abs(b-x);
if (d < 0)
return -1;
if (d > 0)
return 1;
return 0;
}
}
numbers.sort(d_cmp(50));
console.log(numbers);
output:
30,21,4,1,100000
Hemera already answered how to get date distances. The rest, accessing date attributes, should be easy to implement.
For a live demo of above code (combined) see: https://ideone.com/e7DaOx
You can subtract the dates and compare the results. Like new Date("2021-08-18") - new Date("2021-08-17") = 86400000 cause dates are saved as milliseconds from a random but standardize reference date.
Then you can use this difference by using Math.abs(number) as a condition for finding the nearest dates to the given one and put it in a simple sorting function like below:
function orderByDateDistance(nDate, nList){
// easy sorting by finding the current min (also working with max)
for(let tA=0;tA<nList.length-1;tA++){ // iterating over all except the last will be sorted
let tIndex = tA; // current index
let tDifference = Math.abs(nDate-new Date(nList[tA]["date"])); // current difference
for(let tB=tA+1;tB<nList.length;tB++){ // iterating over unsorted list part
if(Math.abs(nDate-new Date(nList[tB]["date"])) < tDifference){ // compare current difference with stored
tIndex = tB; // save index
tDifference = Math.abs(nDate-new Date(nList[tB]["date"])); // save value optional
}
}
// change items
let tBuffer = nList[tA]; // save current object
nList[tA] = nList[tIndex]; // copy next lowest object
nList[tIndex] = tBuffer; // copy buffered object
}
return nList; // optional returning
}
// Your example
console.log(
orderByDateDistance(
new Date("2021/08/18"),
[
{"user": "John", "date": "2021-08-20"},
{"user": "Bob", "date": "2021-08-17"},
{"user": "Joe", "date": "2021-08-09"}
]
)
);
I have an array y like this:
var y = [1, 2, 3, 4];
And I would like to iterate through the array, but exclude some indexes. The indexes are saved in second array
var x = [1,3];
So, I want to write each numbers from an array y, but not the numbers on the position 1,3, which come from array x
I tried to skip the numbers on these positions, but with no success. Could you please help me?
Here is what I tried
for (var i = 0; i < y.length; i++) {
for (var j = 0; j < x.length; j++) {
if (i === x[j]) {
continue;
}
}
console.log(y[i]);
}
Short answer
Prefer using filter over a loop
const xs = [ 1, 2, 3, 4, 5 ] // array of values
const ys = [ 1, 3 ] // indices to skip
// using `filter`
const zs = xs.filter((_, i) => !ys.includes(i))
console.log(zs)
//=> [ 1, 3, 5 ]
Long answer
When possible, you don't want to be using a loop because it can hurt the ability to understand your code taking a procedural approach over a declarative approach. You can instead use a higher-order function like Array.prototype.filter to keep the values you want. The return value of the function passed into filter needs to return a boolean of what to keep. In JavaScript, the filter function is of binary arity, meaning it takes two arguments, with the first argument being the array element and the second being the index. We can ignore the array element value as it is only the index we need to check (this is why the function starts with (_, ...) to drop the first argument).
Array.prototype.includes is a function on the array prototype that lets you know if the array contains a value (i.e. [0].includes(0) === true and [0].includes(1) == false).
Putting these two concepts together, we can iterate over the first array, xs, ignoring the values but using the index to see if it's included in our blacklisted indices array, ys.
If we looked at this as a map function, instead of filter that included our value
xs.map((v, i) => [ v, !ys.includes(i) ])
//=> [ [ 1, true ], [ 2, false ], [ 3, true ], [ 4, false ], [ 5, true ] ]
We can see which values will be true. And if we remember, filter keeps our true values [ 1, 3, 5 ].
You could use the Array.includes() method.
var list = [1,2,3,4];
var skipIndexes = [1,3];
for (var i = 0; i< list.length; i++) {
if (! skipIndexes.includes(i)) {
console.log(list[i]);
}
}
Looks like you were pretty close, but you don't need the inner loop. Just check if the index you're on (i) is one of the members of the array x, and if so, continue. You can do that using the array .includes method, or indexOf if you don't have es6 support.
var y = [1, 2, 3, 4];
var x = [1,3];
for (var i = 0; i < y.length; i++) {
if (x.includes(i)) continue; // Or if not es6 use: `x.indexOf(i) !== -1`
console.log(y[i]);
}
This prints 1 and 3, which are the items of the array y in the 0th and 2nd indices respectively (since we skipped indices 1 and 3).
How to remove row in two dimensional array in JavaScript with row number. If I want to delete all elements in row number 4 then how can do it??
Here's an example of how to remove a row by using splice:
var array = [];
var count = 0;
for (var row=0; row<4; row++) {
array[row] = [];
for (var col=0; col<5; col++) {
array[row][col] = count++;
}
}
console.log(array);
[ [ 0, 1, 2, 3, 4 ],
[ 5, 6, 7, 8, 9 ],
[ 10, 11, 12, 13, 14 ],
[ 15, 16, 17, 18, 19 ] ]
function deleteRow(arr, row) {
arr = arr.slice(0); // make copy
arr.splice(row - 1, 1);
return arr;
}
console.log(deleteRow(array, 4));
[ [ 0, 1, 2, 3, 4 ],
[ 5, 6, 7, 8, 9 ],
[ 10, 11, 12, 13, 14 ] ]
Lets say you have an array 'arr' then you can remove full row by arr.splice(3,1);
I realize this question is old, but it is one of the first results when searching for how to remove from a 2d (multidimensional) array in JS.
Here is what I used to delete the inner array based on a key of the inner array. It should continue to work if there were multiple instances of the same key. In this example, I am searching for, and removing the array with the key of 18.
Sorry about the formatting - it gets the point across.
var items = [
["19", 1],
["18", 2],
["20", 3]
];
//console.log(items);
document.getElementById("a").innerHTML = items;
for (var i = 0; i < items.length; i++) {
if (items[i][0] == "18") {
items.splice(i, 1);
}
}
//console.log(items);
document.getElementById("b").innerHTML = items;
<p>Before</p>
<div id='a'></div>
<p>After</p>
<div id='b'></div>
Just call the splice(4, 1) method, when 4 is row number and 1 is number of rows to remove -
twoDimensionalArray.splice(4, 1); // remove 4th row
Also shift() and pop() are very handy methods which remove first and last rows accordingly -
twoDimensionalArray.shift(); // to remove first row
twoDimensionalArray.pop(); // to remove last row
Here you have a visual example of a bidimensional array with row deletion button (delete by ID) + jQuery preview of the table.
I hope it can be usefull!
JS DELETE ROW from Bidimensional ARRAY + Show on jQuery Cart Table https://jsbin.com/xeqixi/edit?html,js,output
delete array[index];
array.length--;
In your case give index as 4 and execute the above statement and you need to manually reduce the length of array.
i'm tryin' to explain what i want. I have two arrays:
my_array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
my_array_two = ["string", "string", "string", "string", "string", "string", "string", "string", "string", "string" ];
and i need to merge this arrays but in a specific way. The new array will be:
my_new_array = [1, 2, "string", 3, 4, "string", 5, "string", 6, "string", 7, "string", 8, "string", 9, "string", 10, "string", "string", "string" ]
The arrays length can be from 1 to 10.
I can't figure out how can i do this, i hope some help for this task.
Thanks in advance
The only pattern I can deduce from the specific input and output shown is to take two values from the first array, then one value from second array, then again two from the first, then alternate one from each until all values have been used from both arrays.
If that's right then the following code will do it:
// copy first input array into output array
var my_new_array = my_array.slice(0);
// loop over second array
for (var i = 0, j = 2; i < my_array_two.length; i++){
// insert next item into output at position j
my_new_array.splice(j, 0, my_array_two[i]);
// figure out next position to insert
j += (j < 4) ? 3 : 2;
}
If this is an original algorithm, your best best would be too write your own sort algorithm to merge the two.
Not sure what the specific pattern is, but as far as the basic algorithm, I would recommend something like this:
var combined_array = [];
var index1 = 0, index2 = 0;
while ((index1 < my_array.length) && (index2 < my_array_two.length)) {
if (/*you're at the end of either array*/) {
// take the next element from the other one.
}
else {
if (compare(my_array[index1], my_array_two[index2])) {
combined_array.push(my_array[index1]);
++index1;
}
else {
combined_array.push(my_array_two[index2]);
++index2;
}
}
}
Where compare is some function you write that looks a both values and returns true if the first one should come before the second.
I have available to me hundreds of JSON strings. Each of these contains an array of 15-20 words sorted by some predetermined weight. This weight, if it's worth noting, is the amount of times these words are found in some chunk of text. What's the best way of finding similarity between arrays of words that are structured like this?
First idea that came to my head was to create a numerical hash of all the words together and basically compare these values to determine similarity. I wasn't very successful with this, since the resulting hash values of very similar strings were not very close. After some research regarding string comparison algorithms, I come to Stackoverflow in hopes of receiving more guidance. Thanks in advance, and please let me know if you need more details of the problem.
Edit 1: Clarifying what I'm trying to do: I want to determine how similar two arrays are according to the words each of these have. I would also like to take into consideration the weight each word carries in each array. For example:
var array1 = [{"word":"hill","count":5},{"word":"head","count":5}];
var array2 = [{"word":"valley","count":7},{"word":"head","count":5}];
var array3 = [{"word":"head", "count": 6}, {"word": "valley", "count": 5}];
var array4 = [{"word": "valley", "count": 7}, {"word":"head", "count": 5}];
In that example, array 4 and array 2 are more similar than array 2 and array 3 because, even though both have the same words, the weight is the same for both of them in array 4 and 2. I hope that makes it a little bit easier to understand. Thanks in advance.
I think that what you want is "cosine similarity", and you might also want to look at vector space models. If you are coding In Java, you can use the open source S-space package.
(added on 31 Oct) Each element of the vector is the count of one particular string. You just need to transform your arrays of strings into such vectors. In your example, you have three words - "hill", "head", "valley". If your vector is in that order, the vectors corresponding to the arrays would be
// array: #hill, #head, #valley
array1: {5, 5, 0}
array2: {0, 5, 7}
array3: {0, 6, 5}
array4: {0, 5, 7}
Given that each array has to be compared to every other array, you are looking at a serious amount of processing along the lines of ∑(n-1) times the average number of "words" in each array. You'll need to store the score for each comparison, then make some sense of it.
e.g.
var array1 = [{"word":"hill","count":5},{"word":"head","count":5}];
var array2 = [{"word":"valley","count":7},{"word":"head","count":5}];
var array3 = [{"word":"head", "count": 6}, {"word": "valley", "count": 5}];
var array4 = [{"word": "valley", "count": 7}, {"word":"head", "count": 5}];
// Comparison score is summed product of matching word counts
function compareThings() {
var a, b, i = arguments.length,
j, m, mLen, n, nLen;
var word, score, result = [];
if (i < 2) return;
// For each array
while (i--) {
a = arguments[i];
j = i;
// Compare with every other array
while (j--) {
b = arguments[j];
score = 0;
// For each word in array
for (m=0, mLen = b.length; m<mLen; m++) {
word = b[m].word
// Compare with each word in other array
for (n=0, nLen=a.length; n<nLen; n++) {
// Add to score
if (a[n].word == word) {
score += a[n].count * b[m].count;
}
}
}
// Put score in result
result.push(i + '-' + j + ':' + score);
}
}
return result;
}
var results = compareThings(array1, array2, array3, array4);
alert('Raw results:\n' + results.join('\n'));
/*
Raw results:
3-2:65
3-1:74
3-0:25
2-1:65
2-0:30
1-0:25
*/
results.sort(function(a, b) {
a = a.split(':')[1];
b = b.split(':')[1];
return b - a;
});
alert('Sorted results:\n' + results.join('\n'));
/*
Sorted results:
3-1:74
3-2:65
2-1:65
2-0:30
3-0:25
1-0:25
*/
So 3-1 (array4 and array2) have the highest score. Fortunately the comparison need only be one way, you don't have to compare a to b and b to a.
Here is an attempt. The algorithm is not very smart (a difference > 20 is the same as not having the same words), but could be a useful start:
var wordArrays = [
[{"word":"hill","count":5},{"word":"head","count":5}]
, [{"word":"valley","count":7},{"word":"head","count":5}]
, [{"word":"head", "count": 6}, {"word": "valley", "count": 5}]
, [{"word": "valley", "count": 7}, {"word":"head", "count": 5}]
]
function getSimilarTo(index){
var src = wordArrays[index]
, values
if (!src) return null;
// compare with other arrays
weighted = wordArrays.map(function(arr, i){
var diff = 0
src.forEach(function(item){
arr.forEach(function(other){
if (other.word === item.word){
// add the absolute distance in count
diff += Math.abs(item.count - other.count)
} else {
// mismatches
diff += 20
}
})
})
return {
arr : JSON.stringify(arr)
, index : i
, diff : diff
}
})
return weighted.sort(function(a,b){
if (a.diff > b.diff) return 1
if (a.diff < b.diff) return -1
return 0
})
}
/*
getSimilarTo(3)
[ { arr: '[{"word":"valley","count":7},{"word":"head","count":5}]',
index: 1,
diff: 100 },
{ arr: '[{"word":"valley","count":7},{"word":"head","count":5}]',
index: 3,
diff: 100 },
{ arr: '[{"word":"head","count":6},{"word":"valley","count":5}]',
index: 2,
diff: 103 },
{ arr: '[{"word":"hill","count":5},{"word":"head","count":5}]',
index: 0,
diff: 150 } ]
*/
Sort the arrays by word before attempting comparison. Once this is complete, comparing two arrays will require exactly 1 pass through each array.
After sorting the arrays, here is a compare algorithm (psuedo-java):
int compare(array1, array2)
{
returnValue = 0;
array1Index = 0
array2Index = 0;
while (array1Index < array1.length)
{
if (array2Index < array2.length)
{
if (array1[array1Index].word == array2[array2Index].word) // words match.
{
returnValue += abs(array1[array1Index].count - array2[array2Index].count);
++array1Index;
++array2Index;
}
else // account for the unmatched array2 word.
{
// 100 is just a number to give xtra weight to unmatched numbers.
returnValue += 100 + array2[array2Index].count;
++array2Index;
}
}
else // array2 empty and array1 is not empty.
{
// 100 is just a number to give xtra weight to unmatched numbers.
returnValue += 100 + array1[array1Index].count;
}
}
// account for any extra unmatched array 2 values.
while (array2Index < array2.length)
{
// 100 is just a number to give xtra weight to unmatched numbers.
returnValue += 100 + array2[array2Index].count;
}
return returnValue;
}