Home > database >  How to get the number of word occurrences in a 2D array?
How to get the number of word occurrences in a 2D array?

Time:09-11

I've found a solution that gives the correct result when the word is at the same index, within each of the array elements, but in the case below, the term/word searched can be anywhere in the element (beginning or end).

array = 
[
 ["A"], ["earth"], ["20"], ["tunnel"],  
 ["house"], ["earth A"], ["$100"], ["house $100"]
]

Expected result:

result = 
[
 ["A", 2], ["earth", 2], ["20", 1], ["tunnel", 1], 
 ["house", 2], ["earth A", 1], ["$100", 2], ["house $100", 1], 
]

Here's the attempt using the solution above:

array = [
  ["A"],
  ["earth"],
  ["20"],
  ["tunnel"],
  ["house"],
  ["earth A"],
  ["$100"],
  ["house $100"]
];

function count(array) {
  return array.reduce((acc, arr) => {
    for (const item of arr) {
      acc[item] = acc[item] !== undefined ? acc[item]   1 : 1
    }
    return acc
  }, {})
}

console.log(count(array))

Appreciate your help!

CodePudding user response:

So: basically the same as Louys Patrice Bessette's answer but instead of setting the value of the object prop to the current count it assigns an array (word and count) to the value instead, and then updates the count at index 1. Wrapping the operation in Object.values will return only those arrays (as an array).

const data=[["A"],["earth"],["20"],["tunnel"],["house"],["earth A"],["$100"],["house $100"]];

const out = Object.values(data
    .flat()
    .join(' ')
    .split(' ')
    .reduce((acc, word) => {
      acc[word] ??= [ word, 0 ];
        acc[word][1];
      return acc;
    }, {})
  );

console.log(JSON.stringify(out));

Additional documentation

CodePudding user response:

I would flatten the array... Then join the array elements by the spaces to split by the spaces.
That will give an array of words.
Then use reduce to count them.

const array = [
  ["A"],
  ["earth"],
  ["20"],
  ["tunnel"],
  ["house"],
  ["earth A"],
  ["$100"],
  ["house $100"]
];

function count(array) {
  return array.flat().join(" ").split(" ")
    .reduce((acc, word) => {
      acc[word] = acc[word] !== undefined ? acc[word]   1 : 1
    return acc
  }, {})
}

// call the count function
const result = count(array)

// Console log each values
for (const key in result){
  console.log(`The word "${key}" was found ${result[key]} time${result[key] > 1 ? 's' : ''}.`)
}

CodePudding user response:

If you need to support any amount of nested arrays and get EXACT REQUESTED output format, check inline comments:

// Array
array = [
  ["A", "B", ["B", "B B"]],
  ["earth"],
  ["20"],
  ["tunnel"],
  ["house"],
  ["earth A"],
  ["$100"],
  ["house $100"]
];

// Count function
const count = array => {
  // Counter holder
  const counter = {};
  // Recursive function
  const rf = function rf(arr) {
    for(const i of arr) {
      // If item is array, count recursively
      // and skip current cycle
      if(Array.isArray(i)) { rf(i); continue; }
      // Split string
      const iArr = i.split(" ");
      // If array has more then 1 items, count
      // recursively and keep current cycle, as
      // you need to capture and count the
      // whole words group to
      if(iArr.length > 1) rf(iArr);
      // Put word/group in object with value 1
      // If word/group exist, increase counter
      counter[i] ? counter[i]   : counter[i] = 1;
    }
  }(array);

  // Return counter
  return counter;
}

// Do count
const counter = count(array);

// Result comes in object form
console.log(counter);

// But you can format result as you needed
console.log(JSON.stringify(Object.keys(counter).map(key => [key, counter[key]])));

CodePudding user response:

Word Count on a sheet:

function wordcount() {
  const ss = SpreadsheetApp.getActive();
  const sh = ss.getSheetByName("Sheet0");
  sh.clearContents();
  const a = [["A"], ["earth"], ["20"], ["tunnel"], ["house"], ["earth A"], ["$100"], ["house $100"]];
  sh.getRange(1, 1, a.length, a[0].length).setValues(a);
  let o = [... new Set(a.slice().flat().join(' ').split(' '))].map(w => [w, sh.createTextFinder(w).matchCase(true).findAll().length]);
  o.unshift(["Words","Count"]);
  sh.getRange(sh.getLastRow()   2,1,o.length,o[0].length).setValues(o);
}
Original
A
earth
20
tunnel
house
earth A
$100
house $100
Words Count
A 2
earth 2
20 1
tunnel 1
house 2
$100 2

CodePudding user response:

Use String.includes after Array.flat:

/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/ 
const array = [
    ['A'],
    ['earth'],
    ['20'],
    ['tunnel'],
    ['house'],
    ['earth A'],
    ['$100'],
    ['house $100'],
  ],
  arrayFlat = array.flat(),
  counts = array.map(([e]) => [
    e,
    arrayFlat.reduce((a, c) => a   String(c).includes(e), 0),
  ]);
console.table(counts);
<!-- https://meta.stackoverflow.com/a/375985/ -->    <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

  • Related