在 JS 对象中查找重复值或虚假值 - Javascript

Find duplicate or falsy value in a JS object - Javascript

我有一个对象,它可以包含一个重复的 and/or 一个虚假值。我想基于此组成一个对象数组,并根据对不区分大小写的值的检查添加一个新的布尔值 属性。

这是我的:

const obj = {
  a: 'A',
  b: 'B',
  c: 'C',
  d: 'c',
  e: 'E',
  f: ''
}

console.log(Object.keys(obj).map(i => {
  return {
    key: i,
    isDuplicateOrFalsy: _.filter(
        Object.values(obj),
        j =>
        _.trimEnd(_.toLower(j)) ===
        _.trimEnd(
          _.toLower(
            obj[i]
          )
        )
      ).length > 1 ||
      !_.every(
        Object.values(obj),
        Boolean
      )
  }
}))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>

预期输出:

[{
  isDuplicateOrFalsy: false,
  key: "a"
}, {
  isDuplicateOrFalsy: false,
  key: "b"
}, {
  isDuplicateOrFalsy: true,
  key: "c"
}, {
  isDuplicateOrFalsy: true,
  key: "d"
}, {
  isDuplicateOrFalsy: false,
  key: "e"
}, {
  isDuplicateOrFalsy: true,
  key: "f"
}]

请指教

你可以做类似的事情:

const obj = { a: 'A', b: 'B', c: 'C', d: 'C', e: 'E', f: '' };

const res = Object.entries(obj)
            .map(([key, val], i, arr) => ({
                key,
                isDuplicateOrFalsy: !val ||
                  arr.some(([k, v], j) =>
                    j !== i && v.toLowerCase().trim() === val.toLowerCase().trim()
                  )
            }));
                  
console.log(res);

使用 _.toPairs() 将对象转换为 [key, value] 的条目,并按值的小写版本对它们进行分组。平面映射组,并将组中的每个条目映射回一个对象。组中长度大于 1 的任何项目都是重复项。合并对象,并使用 _.at():

以正确的顺序获取项目

const fn = obj => _.at(
  _.merge(..._.flatMap(
    _.groupBy(_.toPairs(obj), ([, v]) => _.lowerCase(v)),
    group => group.map(([key, v]) => ( { [key]:{
      key,
      isDuplicateOrFalsy: group.length > 1 || _.isEmpty(_.trim(v))
    }}))
  )),
  _.keys(obj) 
)


const obj = {"a":"A","b":"B","c":"C","d":"C","e":"E","f":"","g":"c"}

const result = fn(obj)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>

解决方案不包含不必要的循环:

const obj = {
  a: 'A',
  b: 'B',
  c: 'C',
  d: 'C',
  e: 'E',
  f: ''
}
// make array [ [key, value], ...  ] and sort by values 
values = Object.entries(obj).sort((a,b)  => a[1] > b[1])
result = values.map((e,i, arr) => {
  const [key, value] = e;
  const last = values.length -1; // last index
  let isDuplicateOrFalsy = false;
  
  // true conditions = dublicates are near
  if (!value) isDuplicateOrFalsy = true; // falsy check
  else if (i > 0 && i < last  // for middle
      && (arr[i-1][1] === value || arr[i+1][1] === value))  isDuplicateOrFalsy = true;   
  else if (i === 0 && arr[1][1] === value) isDuplicateOrFalsy = true; // for first
  else if (i === last && arr[last-1][1] === value) isDuplicateOrFalsy = true;   // for last


  return {
    key,
    isDuplicateOrFalsy
  }
})

console.log(result)

const obj = {
  a: 'A',
  b: 'B',
  c: 'C',
  d: 'c',
  e: 'E',
  f: ''
};

const isDuplicateOrFalsyByValue = Object
  .values(obj)
  .reduce(
    (result, value) => {
      const caseInsensetiveValue = value.toLowerCase();
      result[caseInsensetiveValue] = result[caseInsensetiveValue] === undefined
        /*
          * If `caseInsensetiveValue` is a falsy value,
            then set `isDuplicateOrFalsy` to `true`
          * Otherwise set it to `false`
        */
        ? !caseInsensetiveValue
        /*
          * If result[caseInsensetiveValue] is `true` (we had a falsy value),
            then this `true` won't hurt
          * Otherwise we have a duplicate at this point
            and should set it to `true` as well.
        */
        : true;

      return result;
    },
    {},
  );

const keysWithDuplicationOrFalsyInfo = Object
  .entries(obj)
  .reduce(
    (result, [key, value]) => [
      ...result,
      {
        isDuplicateOrFalsy: isDuplicateOrFalsyByValue[value.toLowerCase()],
        key,
      },
    ],
    [],
  );
console.log('keysWithDuplicationOrFalsyInfo');
console.log(keysWithDuplicationOrFalsyInfo);

简短且更易读。

const obj = {
  a: 'A',
  b: 'B',
  c: 'C',
  d: 'c',
  e: 'E',
  f: ''
}

// Object map number of occurance of each value. { a: 1, b: 1, c: 2, d: 1 }
const valuesOccurance = _.mapValues(_.groupBy(obj, _.lowerCase), occurances => occurances.length);

// function to check duplicate
const isDuplicate = value => valuesOccurance[_.lowerCase(value)] > 1;

// function to check falsy value
const isFalsy = value => !value;

const result = _.map(obj, (value, key) => {
  return {
    isDuplicateOrFalsy: isFalsy(value) || isDuplicate(value),
    key,
  };
});
console.log({ result })
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.20/lodash.min.js"></script>